监听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. Expression构建DataTable to Entity 映射委托

    namespace Echofool.Utility.Common { using System; using System.Collections.Generic; using System.Dat ...

  2. Effective Java实作Comparator - 就是爱Java

    如果集合或数组内的对象,有1个以上不同的排序逻辑时,那该如何处理呢?尤其是当已经实现了Comparable,又不能变动原本的逻辑时,Mix会采用Comparator来处理. 阅读全文>>

  3. LeetCode_3 sum

    Given an array S of n integers, are there elements a, b, c ? Find all unique triplets in the array w ...

  4. nmap 使用脚本引擎进行扫描

    1.下载nmap(nmap官网). 2.安装nmap. 3.编辑环境变量(windows下所需),保存.

  5. AVR32开发环境搭建

    下面是搭建AVR32开发环境的过程记录: 1.AVR32的编译环境下载  (到这里下载  as5installer-stable-5.1.208-full.exe) 如果你在安装的过程中碰到如下问题: ...

  6. Android开源代码解读のOnScrollListener实现ListView滚屏时不加载数据

    使用ListView过程中,如果滚动加载数据的操作比较费时,很容易在滚屏时出现屏幕卡住的现象,一个解决的办法就是不要在滚动时加载数据,而是等到滚动停止后再进行数据的加载.这同样要实现OnScrollL ...

  7. Python进阶之路---1.3python环境搭建

      python环境安装 windows python环境安装 下载安装包     https://www.python.org/downloads/ 安装并指定安装目录     C:\python2 ...

  8. telnet IP不通/sybase central工具无法连接到数据库

    问题描述:客户端sybase central工具无法连接到数据库 服务端操作系统:RHEL5.8_x64,安装sybase-ASE15.7,端口号4112  IP:192.168.1.220  hos ...

  9. DEV LookUpEdit 使用方法

    public class field { public string Name { get; set; } public string Explain { get; set; } } List< ...

  10. Katana概述

    OWIN owin是web services和framework组件之间的抽象.抽象包括两个核心要素: environment dictionary 这个数据结构存储处理HTTP请求必须的状态和相关的 ...