以前說過, 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的核心實際上是做爲一個觀察者去監聽NSManagedObjectContext的通知。當NSManagedObjectContext發生改變的時候NSFetchedResultsController就知道了變化。因此,咱們初始化一個NSFetchedResultsController的時候,也就監聽了對應的NSManagedObjectContext的通知。具體的是三個通知。
NSManagedObjectContextObjectsDidChangeNotification
NSManagedObjectContextWillSaveNotification
NSManagedObjectContextDidSaveNotification
其實看名字均可以猜想一些他們的具體發出通知的時機。
當任何一個Object中的任何屬性有改變的時候,會發出此通知。而後NSFetchedResultsController會去用設置好的NSFetchRequest查處結果進行參數傳遞。當這些改變發送的時候,咱們就只用在 -controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:判斷改變類型是 NSFetchedResultsChangeUpdate或者 NSFetchedResultsChangeMove就能夠作相應的數據到UI的變動操做了。
這個通知是在刪除Object的狀況下。 這時候可能刪除的是section。用-controller: didChangeSection: atIndex: forChangeType:。 若是隻是一個Object的刪除。就用-controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:。 類型都是NSFetchedResultsChangeDelete.
這個通知對應的delegate方法就是-controller: didChangeSection: atIndex: forChangeType: 和 -controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:。
瞭解了NSFetchedResultsController的原理。事實上本身就能夠寫NSFetchedResultsController了。
事實上,這篇blog寫的確實很糟糕。 並且看日期已經寫了20多天了。這樣的拖沓讓我很不開心。 因此我決定快速的結束這篇blog。 之後就算寫的糟糕也不該該拖沓的。