1.使用場(chǎng)景
? ? 從coreData中獲取存儲(chǔ)的數(shù)據(jù)時(shí),使用謂詞NSpredicte進(jìn)行篩選,排序. 如果篩選的數(shù)據(jù)需要分組或者分頁(yè),就需要對(duì)數(shù)據(jù)再次篩選,使用一些算法也可以實(shí)現(xiàn),但是內(nèi)存消耗很大,并且邏輯不完善可能會(huì)出現(xiàn)其他問題.iOS提供的NSFetchedResultsController,提供高效的查詢分類功能,并把數(shù)據(jù)以分組的形式 展示在 UITableView中.
如:存儲(chǔ)在coreData中的節(jié)數(shù)據(jù),需要取出該課程下所有節(jié) 并按章節(jié)分組:
? ? 在修改數(shù)據(jù)時(shí),?NSManagedObjectContext 數(shù)據(jù)發(fā)生改變變,?NSFetchedResultsController可接收到通知,執(zhí)行代理方法以幫助UITableView顯示的數(shù)據(jù)與coreData存儲(chǔ)數(shù)據(jù)保持一致.
2.使用方法
1) 在使用NSFetchedResultsController的相關(guān)屬性時(shí),需要先創(chuàng)建一個(gè)全局的fetchedResultsController
//用來(lái)存儲(chǔ)查詢并適合TableView來(lái)顯示的數(shù)據(jù)
@property(nonatomic,strong)NSFetchedResultsController *fetchedResultsController;
//通過實(shí)體名獲取請(qǐng)求
NSFetchRequest*request = [[NSFetchRequest alloc]initWithEntityName:@"SectionEntity"];
request.predicate= [NSPredicate predicateWithFormat:@"section_course.courseId = %d",courseId];
//定義分組和排序規(guī)則(按章分組,章節(jié)均是 升序 排列)
NSSortDescriptor*sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"chapterNum" ascending:ascending1];
NSSortDescriptor*sortDescriptor2= [[NSSortDescriptor alloc]initWithKey:@"sectionNum" ascending:ascending2];
//把排序和分組規(guī)則添加到請(qǐng)求中
[requestset SortDescriptors:@[sortDescriptor1,sortDescriptor2]];
//把請(qǐng)求的結(jié)果轉(zhuǎn)換成適合tableView顯示的數(shù)據(jù)
self.fetchedResultsController=[[NSFetchedResultsController alloc] initWithFetchRequest:requestmanagedObjectContext:kManagedObjectContext sectionNameKeyPath:@"chapterNum" cacheName:nil];
... fetchedResultsController創(chuàng)建的相關(guān)參數(shù):
1) NSFetchRequest: 獲取對(duì)象的請(qǐng)求用于獲取對(duì)象. 可以設(shè)置request的entityName, predicate以及sortDescriptors等屬性圈定對(duì)象并排序.
2) NSManagedObjectContext: 上下文,持有獲取的對(duì)象. 通過上下文可以操作coreData,修改數(shù)據(jù),但是如果未save,只是修改了內(nèi)存中數(shù)據(jù),并未保存到磁盤.
3) sectionNameKeyPath: 獲取的對(duì)象進(jìn)行分組的參數(shù).
4) cacheName:緩存名字.個(gè)人理解:只緩存部分?jǐn)?shù)據(jù)在磁盤上面,在需要請(qǐng)求時(shí),根據(jù)時(shí)間戳檢查本地緩存的數(shù)據(jù),但是處理任何非法的或任務(wù)就不檢查舟肉,可以設(shè)置為nil.(API解釋: cacheName - Section info is cached persistently to a private file under this name. Cached sections are checked to see if the time stamp matches the store, but not if you have illegally mutated the readonly fetch request, predicate, or sort descriptor.)
... NSFetchedResultsController 一個(gè)缺陷: :
使用 sortKey1 作為分組依據(jù)黄选,就必須得使用 sortKey1 作為第一排序依據(jù)。
如: 使用 chapterSeq 章節(jié)號(hào) 分組, 組別 按照 章節(jié)號(hào) 排序
使用chapterName 章節(jié)名 分組, 組別 按照 章節(jié)名 排序.
以下例舉兩種情況:
(1)可作為分組的 參數(shù) 未作為第一排序依據(jù),驚嚇如下:(出現(xiàn)率100%)
因:
果:
(2)使用可作為分組的另一參數(shù),驚嚇如下:(出現(xiàn)率5%)
因:
果:
2) 使用NSFetchedResultsController的相關(guān)屬性/方法,在UITableview中展示
UITableView 代理方法:
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
//我們的數(shù)據(jù)中有多少個(gè)section, fetchedResultsController中的sections方法可以以數(shù)組的形式返回所有的section
//sections數(shù)組中存的是每個(gè)section的數(shù)據(jù)信息
if(nil==_fetchedResultsController) {
return 0;
?}
NSArray*sections = [self.fetchedResultsControllersections];
return sections.count;
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
NSArray*sections = [self.fetchedResultsControllersections];
id <NSFetchedResultsSectionInfo>?sectionInfo = sections[section];
//返回每個(gè)section中的元素個(gè)數(shù)
return[sectionInfo numberOfObjects];
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
//通過[self.fetchedResultsController objectAtIndexPath:indexPath]直接獲取對(duì)象
MCVideoCacheEntity*videoEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];
if(videoEntity ==nil) {
return nil;
?}
//....................................中間省略
}
補(bǔ)充:
需要的其他信息可以在以下相關(guān)屬性/方法中查找:
NSFetchedResultsController屬性 , 方法
NSFetchedResultsSectionInfo 屬性 , 方法
如:[sectionInfo name] 可以獲取分組的組信息:
chapterName作為分組依據(jù),結(jié)果即為章名;
chapterNum作為分組依據(jù),結(jié)果即為章號(hào);
3) 添加NSFetchedResultsController的代理方法,幫助UITableView顯示的數(shù)據(jù)與coreData存儲(chǔ)數(shù)據(jù)保持一致
//當(dāng)CoreData的數(shù)據(jù)正在發(fā)生改變時(shí)岂嗓,F(xiàn)RC產(chǎn)生的回調(diào)("controllerWillChangeContent"與"controllerDidChangeContent"此處不寫,添加行暫未出現(xiàn)異常,添加一個(gè)新的分區(qū)數(shù)據(jù)可能會(huì)crash)
- (void)controllerWillChangeContent:(NSFetchedResultsController*)controller {
[_downLoadListTbl beginUpdates];
}
//分區(qū)改變狀況
- (void)controller:(NSFetchedResultsController*)controller didChangeSection:(id)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
caseNSFetchedResultsChangeInsert:
[self.downLoadListTbl insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
caseNSFetchedResultsChangeDelete:
[self.downLoadListTbl deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
?}
}
//數(shù)據(jù)改變狀況
- (void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath*)newIndexPath {
UITableView*tableView =self.downLoadListTbl;
switch(type) {
caseNSFetchedResultsChangeInsert:
//讓tableView在newIndexPath位置插入一個(gè)cell
[tableViewinsertRowsAtIndexPaths:[NSArrayarrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
caseNSFetchedResultsChangeDelete:
[tableViewdeleteRowsAtIndexPaths:[NSArrayarrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
caseNSFetchedResultsChangeUpdate:
//讓tableView刷新indexPath位置上的cell
[tableViewreloadRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationNone];
break;
caseNSFetchedResultsChangeMove:
[tableViewdeleteRowsAtIndexPaths:[NSArrayarrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableViewinsertRowsAtIndexPaths:[NSArrayarrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
?}
}
//當(dāng)CoreData的數(shù)據(jù)完成改變是互站,F(xiàn)RC產(chǎn)生的回調(diào)
- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller {
[self.downLoadListTbl endUpdates];
}
........................................................................................................................................
本文 NSFetchedResultsController + CoreData + UITableView的完美結(jié)合,只是在基本功能上簡(jiǎn)單介紹,更完美的功能還待使用者發(fā)掘......(歡迎批評(píng)指正~~)