ios - 在 Swift 中完成后立即从表中删除所有行

标签 ios swift core-data

在我的应用程序中,我希望能够一次删除特定表的所有行,并在完成 block 调用时重新加载表。

我知道如何删除单行:

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        switch editingStyle {
        case .Delete:
            // remove the deleted item from the model
            let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
            let context:NSManagedObjectContext = appDel.managedObjectContext!
            context.deleteObject(myData[indexPath.row] as NSManagedObject)
            myData.removeAtIndex(indexPath.row)
            context.save(nil)

           //tableView.reloadData()
            // remove the deleted item from the `UITableView`
            self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        default:
            return

        }
}

我也知道我可以获取所有行并在循环中将它们一一删除,但我正在努力解决如何向其添加完成 block ,以便我可以在删除完成后重新绘制表格。

我们非常感谢任何形式的帮助。

最佳答案

下面是一些示例代码。通常的方法是在后台线程上执行大的删除或添加操作,然后使用通知来触发主线程上的合并。因此下面的代码假设如下:

  • 您有一个主要的ManagedObjectContext,供
    使用 TableView 中的 FetchedResultsController
  • 您有一个辅助函数来启动删除或加载方法 后台线程
  • 您创建后台 ManagedObjectContexts 并注册 ContextDidSave 通知,然后您可以使用它来合并更改 进入主要上下文

用于调用加载或删除的辅助函数。

- (void)deleteDataInBackground {

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
                [self deleteData];
            });
}

加载函数

    /* Loads the required seed data */
    // Usually called on a background thread and therefor we need to process the DidSave notification
    // to merge the changed with the main context so the UI gets updated
    func loadData() {
        //FLOG(" called");

        let bgContext:NSManagedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.ConfinementConcurrencyType)

        // Register for saves in order to merge any data from background threads
        NSNotificationCenter.defaultCenter().addObserver(self, selector:"storesDidSave:", name: NSManagedObjectContextDidSaveNotification, object:bgContext)

        while (persistentStoreCoordinator == nil) {
            //FLOG(@" persistentStoreCoordinator = nil, waiting 5 seconds to try again...");
            sleep(5);
        }

        bgContext.persistentStoreCoordinator = persistentStoreCoordinator



        insertStatusCode(bgContext, number: 0, name: "Not started")
        insertStatusCode(bgContext, number: 1, name: "Started on track")
        insertStatusCode(bgContext, number: 2, name: "Behind schedule")
        insertStatusCode(bgContext, number: 3, name: "Completed")
        insertStatusCode(bgContext, number: 4, name: "Completed behind schedule")
        insertStatusCode(bgContext, number: 5, name: "On hold or cancelled")


        bgContext.processPendingChanges()

        do {

            try bgContext.save()

            //FLOG(" Seed data loaded")

        } catch {
            //FLOG("  Unresolved error \(error), \(error?.userInfo)")
        }
    } 


Code to insert new records

    func insertStatusCode(moc:NSManagedObjectContext, number:Int, name:String)
    {
        //FLOG(" called")

        if let newManagedObject:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName("StatusCode", inManagedObjectContext:moc) {

            newManagedObject.setValue(number, forKey:"number")
            newManagedObject.setValue(name, forKey:"name")

        }        
    }

用于处理通知并将更改合并到主上下文中的代码

// NB - this may be called from a background thread so make sure we run on the main thread !!
// This is when transaction logs are loaded
func storesDidSave(notification: NSNotification!) {

    // Ignore any notifications from the main thread because we only need to merge data
    // loaded from other threads.
    if (NSThread.isMainThread()) {
        //FLOG(" main thread saved context")
        return
    }

    NSOperationQueue.mainQueue().addOperationWithBlock {
        //FLOG("storesDidSave ")
        // Set this so that after the timer goes off we perform a save
        // - without this the deletes don't appear to trigger the fetchedResultsController delegate methods !
        self.import_or_save = true

        self.createTimer() // Timer to prevent this happening too often!
        if let moc = self.managedObjectContext {
            moc.mergeChangesFromContextDidSaveNotification(notification)
        }

    }
}

这是一个 Obj-C 删除函数,请注意,有一些检查以确保对象没有被另一个线程删除...

- (void)deleteData {
    FLOG(@"deleteData called");
    _deleteJobCount++;
    [self postJobStartedNotification];

    FLOG(@" waiting 5 seconds...");
    sleep(5);
    [self showBackgroundTaskActive];

    NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

    // Register for saves in order to merge any data from background threads
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(storesDidSave:) name: NSManagedObjectContextDidSaveNotification object:bgContext];


    while (self.persistentStoreCoordinator == nil) {
        FLOG(@" persistentStoreCoordinator = nil, waiting 5 seconds to try again...");
        sleep(5);
    }

    bgContext.persistentStoreCoordinator = [self persistentStoreCoordinator];

    FLOG(@" fetching data...");

    NSArray *companies = [self getData:@"Company" sortField:@"name" predicate:nil managedObjectContext:bgContext];

    NSUInteger count = companies.count;

    if (count>2) {
        for (int i = 0; i<3; i++) {
            NSManagedObject *object = [companies objectAtIndex:i];

            // Must wrap this incase another thread deleted it already
            @try {
                if ([object isDeleted]) {
                    FLOG(@" object has been deleted");
                } else {
                    FLOG(@" deleting %@", [object valueForKey:@"name"]);
                    [bgContext deleteObject:object];
                    [bgContext processPendingChanges];
                    NSError *error = nil;
                    if (![bgContext save:&error]) {
                        FLOG(@"  Unresolved error %@, %@", error, [error userInfo]);
                    }
                }
            }
            @catch (NSException *exception) {
                FLOG(@" error deleting object");
                FLOG(@"   exception is %@", exception);
            }


            FLOG(@"   waiting 5 seconds...");
            sleep(0.01);
        }

    }

    [[NSNotificationCenter defaultCenter] removeObserver:self name: NSManagedObjectContextDidSaveNotification object:bgContext];

    /*
     dispatch_async(dispatch_get_main_queue(),^(void){
     [[NSNotificationCenter defaultCenter] removeObserver:self name: NSManagedObjectContextDidSaveNotification object:nil];
     });
     */

    FLOG(@" delete ended...");
    [self showBackgroundTaskInactive];
    _deleteJobCount--;
    [self postJobDoneNotification];

}

如果您有大批量数据,请查看核心数据批处理函数。

关于ios - 在 Swift 中完成后立即从表中删除所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31122861/

相关文章:

ios - 如何在我的容器 View 中嵌入 "remove"segue,或完全删除容器 View ?

iPhone 核心数据和多线程

javascript - 如何在 React Native 中运行后台任务?

swift - 如何使用 react-native 组件创建一个 swift 项目?

ios - UISearchController 与 UITableView 重叠,这使我无法为单元格呈现详细的 ViewController

ios - Swift - 如何将 View Controller 的引用传递给子 UIView 类?

ios 如何正确使用 NSPredicate 将 NSString 与核心数据匹配?

objective-c - 如何使用 NSPredicate 按相关性对搜索结果进行排序?

ios - 是否可以通过 iOS 中的应用内购买进行后付款?

ios - 何时使用 MKMapView 的 MKUserTrackingMode vs 位置管理器的开始更新位置?