监听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。 以后就算写的糟糕也不应该拖沓的。

CoreData (四)备的更多相关文章

  1. CoreData (三)备

    NSFetchedResultsController 什么是NSFetchedResultsController NSFetchedResultsController是一个让人爱恨交加的一个类.如果使 ...

  2. DataGuard相同SID物理Standby搭建

    Oracle Data Guard 是针对企业数据库的最有效和最全面的数据可用性.数据保护和灾难恢复解决方案.它提供管理.监视和自动化软件基础架构来创建和维护一个或多个同步备用数据库,从而保护数据不受 ...

  3. Nginx系列篇四:Nginx+keepalived搭建一个高可用的双机双主热备

    建议:先阅读Nginx+keepalived主从配置,因为此篇是接着上篇开始的 上一篇我们简单的介绍了主从配置及其缺点,我们看一下双主热备配置: 2台Nginx+keepalived互为主备,各自绑定 ...

  4. iOS开发——数据持久化Swift篇&(四)CoreData

    CoreData import CoreData class ViewController: UIViewController { override func viewDidLoad() { supe ...

  5. 备忘--简单比较SPSS、RapidMiner、KNIME以及Kettle四款数据分析工具

    SPSS.RapidMiner.KNIME以及Kettle四款工具都可以用来进行数据分析,只是彼此有各自的侧重点和有劣势.它们都可以逐步的定义数据分析过程,也同样都可以对数据进行ETL处理.笔者从自己 ...

  6. 游戏音频技术备忘 (四) Wwise Unreal Engine 集成代码浅析 (一)

    在Engine\Plugins\Wwise\Source下为主要Wwise相关代码,AkAudio文件夹下为运行时相关代码,AudiokineticTools下为编辑器工具相关代码,Audiokine ...

  7. nginx:负载均衡实战(四)nginx+keepalived配置双机热备

    1.下载安装 下载keepalived地址:http://www.keepalived.org/download.html 解压安装: tar -zxvf keepalived-.tar.gz 安装o ...

  8. iOS:CoreData数据库的使用四(数据库和UITableViewController以及NSFetchedResultsController一起使用)

    CoreData数据库虽然可以和tableview或者UITableViewController一起使用将数据显示在表格上,但是在准备数据的时候,这种方式需要用一个可变数组来装从数据库一次性取出来的所 ...

  9. BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子

    来源:旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标 BZOJ又崩了,直接贴一下人家的代码. 代码: #include"stdio.h" #include"str ...

随机推荐

  1. Swift 可选类型-备

    我们先看看如下代码: var n1: Int = 10 n1 = nil         //编译错误 let str: String = nil    //编译错误 Int和String类型不能接受 ...

  2. Jquery让图片根据浏览器窗口大小自动缩放

    (function($){ $.fn.resizeimage = function(){ var imgLoad = function (url, callback) { var img = new ...

  3. 【剑指offer】面试题38:数字在排序数组中出现的次数

    题目: 统计一个数字在排序数组中出现的次数. 思路: 对二分查找进行改进,找到数字在数组中第一次出现和最后一次出现的位置,这样就得到它出现的次数. 以找第一次出现的位置为例:如果mid元素大于k,则在 ...

  4. ssh秘钥交换详解与实现 diffie-hellman-group-exchange-sha

    ssh的DH秘钥交换是一套复合几种算法的秘钥交换算法.在RFC4419中称为diffie-hellman-groupX-exchange-shaX 的算法(也有另一种单纯的 rsaX-shaX 交换算 ...

  5. 高性能以太网芯片W5500 数据手册 V1.0(一)

    W5500 W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案.W5500 集成了 TCP/IP 协议栈,10/100M 以太网数据链路层(MAC) ...

  6. C# - List操作 - 按照字母排序

    有Family的类如下: public class FamilyModel { public string Name { set; get; } } 创建List List<FamilyMode ...

  7. pyqt小例子 treewidget

    # -*- coding: cp936 -*- from PyQt4.QtCore import * from PyQt4.QtGui import * class InlineEditor(QWid ...

  8. Window7下vagrant的部署

    1. 下载并安装VirtualBox     下载地址:https://www.virtualbox.org/wiki/Downloads,下载最新的安装包,接下来的安装步骤就是下一步下一步了,你懂的 ...

  9. [TypeScript] Avoid any type

    To avoid using "any" type is a best pratice. The reason for that is it disable the power o ...

  10. [转]iOS hybrid App 的实现原理及性能监测

    转自:http://www.cocoachina.com/ios/20151118/14270.html iOS hybrid App 的实现原理及性能监测 2015-11-18 11:39 编辑:  ...