CoreData (四)備

監聽NSFetchedResultsController

以前說過, NSFetchedResultsController是有兩個重要的功能。fetch

第一:NSFetchedResultsController是做用在Core Data上的,經過NSFetchRequest來查詢Core Data裏面的數據.能夠返回按照組分好的數據.這樣便於UITableView來顯示.動畫

第二:但Model改變的時候NSFetchedResultsController能及時的發出通知.準確的說,應該是當NSManagedObjectContext發生改變的時候,NSFetchedResultsController能知道這些變化,而後發出通知出來.以便UITableview能及時的更新.spa

上一篇寫了第一點. 如今寫第二點..net

 

背景

若是在數據改變了的時候,咱們用UITableView reload. 整個UITableView的數據確實能保持最新的狀況. 可是問題是這樣作的效率很低. 更但願的狀況是,我哪一條數據增長,修改,刪除. 就對應着UITableView裏面的那一條數據在UI上增長,修改,刪除.這樣效率會有很大的提高.code

直接操做

首先是用Delegate來進行UITableView的改變.blog

第一個方法,告訴UITableView數據要開始更新了,你UITableView趕忙準備好更新.ci

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

固然有開始就有結束,下面的方法就是告訴UITableView結束更新.get

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

這兩個方法一看命名規則就能看出來是一個Delegate.在NSFetchedResultsController將要變換的時候,咱們開啓UITableView的編輯,而後在NSFetchedResultsController已經改變結束的時候結束UITableView的編輯.思惟上天然而然,善始善終.string

接下來咱們要在begin和end之間對tableview作出改變.it

改變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。 之後就算寫的糟糕也不該該拖沓的。

相關文章
相關標籤/搜索