zoukankan      html  css  js  c++  java
  • CoreData (四)备

    监听NSFetchedResultsController

    之前说过, NSFetchedResultsController是有两个重要的功能。

    第一:NSFetchedResultsController是作用在Core Data上的,通过NSFetchRequest来查询Core Data里面的数据.可以返回按照组分好的数据.这样便于UITableView来显示.

    第二:但Model改变的时候NSFetchedResultsController能及时的发出通知.准确的说,应该是当NSManagedObjectContext发生改变的时候,NSFetchedResultsController能知道这些变化,然后发出通知出来.以便UITableview能及时的更新.

    上一篇写了第一点. 现在写第二点.

    背景

    如果在数据改变了的时候,我们用UITableView reload. 整个UITableView的数据确实能保持最新的情况. 但是问题是这样做的效率很低. 更希望的情况是,我哪一条数据增加,修改,删除. 就对应着UITableView里面的那一条数据在UI上增加,修改,删除.这样效率会有很大的提升.

    直接操作

    首先是用Delegate来进行UITableView的改变.

    第一个方法,告诉UITableView数据要开始更新了,你UITableView赶紧准备好更新.

    1
    2
    3
    - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
    {    [[self tableView] beginUpdates];
    }

    当然有开始就有结束,下面的方法就是告诉UITableView结束更新.

    1
    2
    3
    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    {    [[self tableView] endUpdates];
    }

    这两个方法一看命名规则就能看出来是一个Delegate.在NSFetchedResultsController将要变换的时候,我们开启UITableView的编辑,然后在NSFetchedResultsController已经改变结束的时候结束UITableView的编辑.思维上自然而然,有始有终.

    接下来我们要在begin和end之间对tableview做出改变.

    改变section的方法.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    - (void)controller:(NSFetchedResultsController *)controller
      didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
               atIndex:(NSUInteger)sectionIndex
         forChangeType:(NSFetchedResultsChangeType)type{    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:sectionIndex];
        switch(type) {        case NSFetchedResultsChangeInsert:
            {
                [[self tableView] insertSections:indexSet
                                withRowAnimation:UITableViewRowAnimationFade];            break;
            }
            case NSFetchedResultsChangeDelete:
            {
                [[self tableView] deleteSections:indexSet
                                withRowAnimation:UITableViewRowAnimationFade];
                break;
                 
            }
        }
    }

    这个方法是在section改变的时候调用.改变类型支持两种NSFetchedResultsChangeInsert和NSFetchedResultsChangeDelete..这样我们能操作UITableView里面section变化了.

    接下来的方法是改变cell内容的.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
           atIndexPath:(NSIndexPath *)indexPath
         forChangeType:(NSFetchedResultsChangeType)type
          newIndexPath:(NSIndexPath *)newIndexPath
    {    NSArray *newArray = [NSArray arrayWithObject:newIndexPath]; NSArray *oldArray = [NSArray arrayWithObject:indexPath]; switch(type) {        case NSFetchedResultsChangeInsert:
                [[self tableView] insertRowsAtIndexPaths:newArray
                                        withRowAnimation:UITableViewRowAnimationFade];            break;        case NSFetchedResultsChangeDelete:
                [[self tableView] deleteRowsAtIndexPaths:oldArray
                                        withRowAnimation:UITableViewRowAnimationFade];            break;        case NSFetchedResultsChangeUpdate: {            UITableViewCell *cell = nil;            NSManagedObject *object = nil;            cell = [[self tableView] cellForRowAtIndexPath:indexPath];            object = [[self fetchedResultsController] objectAtIndexPath:indexPath]; [[cell textLabel] setText:[object valueForKey:@"name"]];            break;
            }
            case NSFetchedResultsChangeMove:
                 
                [[self tableView] deleteRowsAtIndexPaths:oldArray
                                        withRowAnimation:UITableViewRowAnimationFade];
                [[self tableView] insertRowsAtIndexPaths:newArray
                                        withRowAnimation:UITableViewRowAnimationFade];
            break; }
    }

    在这个方法里面我们可以增删改Cell的.并且可以有动画.

    NSFetchedResultsController的原理

    上面我们已经可以无痛的使用NSFetchedResultsController了。而且各种数据都可以自动更新,但是它是一个什么原理呢?

    NSFetchedResultsController的核心其实是作为一个观察者去监听NSManagedObjectContext的通知。当NSManagedObjectContext发生改变的时候NSFetchedResultsController就知道了变化。所以,我们初始化一个NSFetchedResultsController的时候,也就监听了对应的NSManagedObjectContext的通知。具体的是三个通知。

    NSManagedObjectContextObjectsDidChangeNotification

    NSManagedObjectContextWillSaveNotification

    NSManagedObjectContextDidSaveNotification

    其实看名字都可以猜测一些他们的具体发出通知的时机。

    NSManagedObjectContextObjectsDidChangeNotification

    当任何一个Object中的任何属性有改变的时候,会发出此通知。然后NSFetchedResultsController会去用设置好的NSFetchRequest查处结果进行参数传递。当这些改变发送的时候,我们就只用在 -controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:判断改变类型是 NSFetchedResultsChangeUpdate或者 NSFetchedResultsChangeMove就可以做相应的数据到UI的变更操作了。

    NSManagedObjectContextWillSaveNotification

    这个通知是在删除Object的情况下。 这时候可能删除的是section。用-controller: didChangeSection: atIndex: forChangeType:。 如果只是一个Object的删除。就用-controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:。 类型都是NSFetchedResultsChangeDelete.

    NSManagedObjectContextDidSaveNotification

    这个通知对应的delegate方法就是-controller: didChangeSection: atIndex: forChangeType: 和 -controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:。

    了解了NSFetchedResultsController的原理。事实上自己就可以写NSFetchedResultsController了。

    事实上,这篇blog写的确实很糟糕。 而且看日期已经写了20多天了。这样的拖沓让我很不开心。 所以我决定快速的结束这篇blog。 以后就算写的糟糕也不应该拖沓的。

  • 相关阅读:
    AcWiing 翻硬币
    AcWing 飞行员兄弟 二进制枚举
    AcWing 费解的开关 二进制枚举
    vue发送短信逻辑
    使用celery异步发送短信
    celery配置与基本使用
    celery原理与组件
    短信验证接口
    图片验证码接口
    编写注册接口
  • 原文地址:https://www.cnblogs.com/isItOk/p/5357360.html
Copyright © 2011-2022 走看看