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

时间:2015-06-29 18:23:28

标签: ios swift core-data

在我的应用程序中,我希望能够立即删除特定表的所有行,并在完成块调用上重新加载表。

我知道如何删除一行:

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

        }
}

我也知道我可以获取所有行并在循环中逐个删除它们,但我正在努力如何向其添加完成块,因此我可以在删除完成后重绘表。 / p>

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

3 个答案:

答案 0 :(得分:0)

基本上,您需要做的就是在完成块中执行您想要执行的操作 - 只需从数据源中删除所有项目并更新表格。 UITableView数据源委托方法将为您完成剩下的工作并清空tableView。

答案 1 :(得分:0)

只需使用deleteRowsAtIndexPaths:withRowAnimation:方法并应用以下问题的代码 - How to detect that animation has ended on UITableView beginUpdates/endUpdates?

它将为您提供正在查找的完成块功能,因此您可以在其中调用reloadData。

对于Swift,它看起来如下:

CATransaction.begin()
CATransaction.setCompletionBlock {
    //Reload data here
}

tableView.beginUpdates()
//Remove cells here
tableView.endUpdates()

CATransaction.commit()

答案 2 :(得分:0)

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

  • 您有一个主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];

}

如果您有大量批处理,请查看Core Data批处理函数。