【问题标题】:how to force core data reload from persistent storage after cellEdit如何在 cellEdit 之后强制从持久存储重新加载核心数据
【发布时间】:2016-12-06 04:25:10
【问题描述】:

编辑单元格后,我无法从核心数据持久存储重新加载数据。

我尝试重新加载 tableView 本身,但这不会强制从持久存储中获取,我该如何强制重新加载?

这是我重新加载的尝试,但如果我退出 UIViewController 并返回所有工作,那么我知道持久存储已正确更新

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];

    NSManagedObjectContext *context = appDelegate.persistentContainer.viewContext;

    if([NWTillHelper isDebug] == 1) {
        NSLog(@"TransactionListView:tableView:context = %@", context);
    }

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSManagedObject *transactionRow = [self.transactionRowsRows objectAtIndex:indexPath.row];

        [transactionRow setValue:[NSNumber numberWithInt:[@"999" intValue]] forKey:@"status"];
        [transactionRow setValue:[NSNumber numberWithInt:[@"0" intValue]] forKey:@"qty"];
        [transactionRow setValue:[NSDecimalNumber decimalNumberWithString:@"0"] forKey:@"price"];
        [transactionRow setValue:[NSDecimalNumber decimalNumberWithString:@"0"] forKey:@"discountPercentage"];
        [transactionRow setValue:[NSDecimalNumber decimalNumberWithString:@"0"] forKey:@"discountAmount"];
        [transactionRow setValue:[NSDecimalNumber decimalNumberWithString:@"0"] forKey:@"amountTax"];
        [transactionRow setValue:[NSDecimalNumber decimalNumberWithString:@"0"] forKey:@"sum"];

        NSError *error = nil;
        if (![context save:&error]) {
            if([NWTillHelper isDebug] == 1) {
                NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]);
                return;
            }
        }
        [self.transactionListViewTbl reloadData];
    }
}

【问题讨论】:

    标签: ios uitableview core-data


    【解决方案1】:

    只是想提一下。

    阅读您的问题后,我觉得它不会使用 Fetch Controller 来修复。 Fetch Controller 非常简洁,它可以让您保持表格更新,而无需显式调用 [table reloadData]。但是,如果重新加载您的表数据没有得到更新,您可能有多个托管对象上下文更新您的持久存储。

    数据由不同的托管对象上下文更新,并且您没有在连接表的那个上下文中获得更新。我将从查看我的核心数据堆栈和托管对象上下文的数量开始。如果您需要超过 1 个,您可以订阅更改,或者确保您希望看到的更改是在同一个托管对象上下文中完成的。

    希望对你有帮助。

    Managed Object Context - Apple Docs

    【讨论】:

    • 我在每个方法中都有一个托管对象上下文,但在同一个方法中我只有一个,它会在方法之间发生冲突吗?如果是这样,我怎样才能制作一个在所有方法中都持久的?
    • 谢谢,我有两个上下文竞争我是一个复制和粘贴错误,我认为很多深夜编码,感谢您对此的提醒。
    【解决方案2】:

    使用 NSFetchedResultsController 作为数据源并实现 NSFecthedResultsController 委托

    您可以在 viewController 中创建 NSFetchedResults 控制器作为属性,创建它的单个实例

    lazy var transactionFetchedResultsController : NSFetchedResultsController<Transaction> = {
            let appdelegate = UIApplication.shared.delegate as! AppDelegate
            var fetchedResultsController : NSFetchedResultsController< Transaction >!
    
            appdelegate.managedObjectContext.performAndWait {
                var fetchRequest: NSFetchRequest< Transaction >
                if #available(iOS 10.0, *) {
                    fetchRequest = Transaction.fetchRequest()
                } else {
                    fetchRequest  = NSFetchRequest(entityName: "Transaction")
                }
    
                fetchRequest.sortDescriptors = [NSSortDescriptor(key: "your_property", ascending: true)]
                let yourPredicate = NSPredicate(format: "your condition == whatever")
                fetchRequest.predicate = yourPredicate
                fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: appdelegate.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
            }
            return fetchedResultsController
        }()
    

    为您的 viewController 设置委托

    self. transactionFetchedResultsController.delegate = self
    

    最后在viewDidLoad()中初始化

    try! self. transactionFetchedResultsController.performFetch()
    

    现在实现委托:)

    extension YourViewController : NSFetchedResultsControllerDelegate{
        func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
            //row updated
        }
    
        func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
            //section updated
        }
    
        func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
            //change completed
            //reload your tableView
        }
    }
    

    编辑

    如果您想知道如何使用 NSFetchedResultsController 作为 tableView 数据源?

    extension YourViewController: UITableViewDataSource {
        func numberOfSections(in tableView: UITableView) -> Int {
            return (self. transactionFetchedResultsController.sections?.count)!
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
               //assuming you have only one section
               //you can always return number of items in each section using NSFetchedResultsController :)
                return (self. transactionFetchedResultsController.fetchedObjects?.count)!
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            //let cell = ....
            //you can instantiate your cell here
            //you can access your transaction as below
            let transaction = self. transactionFetchedResultsController.fetchedObjects![indexPath.row]
            //return your cell
            return cell
        }
    }
    

    希望对你有帮助:)

    【讨论】:

    • 这看起来不错,我正在尝试翻译成 ObjC
    • @matt-douhan : 抱歉,哥们没有客观的 C 代码示例,从现在开始就停止了它的工作:(
    • @matt-douhan : Bingo :) 请考虑接受答案,以防它有效并帮助你:)
    猜你喜欢
    • 2012-12-15
    • 2011-08-11
    • 2017-06-22
    • 2013-07-11
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多