coredata学习总结(六)

Connecting the Model to Views

在os x中,core data被设计为通过cocoa绑定同user interface来交互。但是,cocoa 绑定并不是user interface中的一部分。在ios中,你使用NSFetchedResultsController来将model(core data)和views(storyboards)来连接。

NSFetchedResultsController 提供了core data和UITableView 对象之间的接口。因为table views是最常见的展示数据的方式之一,uitableview被设计为处理数据的展示。

Creating a Fetched Results Controller

典型的,一个NSFetchedResultsController实例会被UITableViewController实例来初始化。这个初始化可以在viewDidLoad或者viewWillAppear方法中被实现。或者在view controller的其它地方被初始化。这个例子展示了NSFetchedResultsController的初始化方法。

  1. @property (nonatomic,strong) NSFetchedResultsController*fetchedResultsController;
  2.  
  3. - (void)initializeFetchedResultsController
  4. {
  5. NSFetchRequest *request = [NSFetchRequestfetchRequestWithEntityName:@"Person"];
  6.  
  7. NSSortDescriptor *lastNameSort = [NSSortDescriptor sortDescriptorWithKey:@"lastName"ascending:YES];
  8.  
  9. [requestsetSortDescriptors:@[lastNameSort]];
  10.  
  11. NSManagedObjectContext *moc = …;//Retrieve the main queue NSManagedObjectContext
  12.  
  13. [self setFetchedResultsController:[[NSFetchedResultsControlleralloc] initWithFetchRequest:requestmanagedObjectContext:moc sectionNameKeyPath:nil cacheName:nil]];
  14. [[selffetchedResultsController] setDelegate:self];
  15.  
  16. NSError *error= nil;
  17. if (![[selffetchedResultsController] performFetch:&error]){
  18. NSLog(@"Failed to initialize FetchedResultsController: %@\n%@",[error localizedDescription],[error userInfo]);
  19. abort();
  20. }
  21. }
  1. var fetchedResultsController:NSFetchedResultsController!
  2.  
  3. func initializeFetchedResultsController() {
  4. let request =NSFetchRequest(entityName: "Person")
  5. let departmentSort =NSSortDescriptor(key: "department.name", ascending: true)
  6. let lastNameSort =NSSortDescriptor(key: "lastName", ascending: true)
  7. request.sortDescriptors = [departmentSort,lastNameSort]
  8.  
  9. let moc =dataController.managedObjectContext
  10. fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc,sectionNameKeyPath: "department.name",cacheName: "rootCache")
  11. fetchedResultsController.delegate =self
  12.  
  13. do {
  14. try fetchedResultsController.performFetch()
  15. } catch {
  16. fatalError("Failed to initialize FetchedResultsController:\(error)")
  17. }
  18. }

首先要构造一个fetch请求,NSFetchRequest,这位于NSFetchedResultsController的重要位置。注意fetch请求包含一个排序描述,NSSortDescriptorNSFetchedResultsController至少需要一个排序descriptor来控制将要呈现数据的显示顺序。

一旦fetch请求被初始化了,你就可以初始化NSFetchedResultsController实例了。fetched results controller会要求你传给他一个NSFetchRequest实例和NSFetchRequest对象引用。sectionNameKeyPathcacheName属性都是可选的。

一旦fetched results controller被初始化了,你就分配一个 i 饿delegate。这个delegate会在有数据变化时通知table view controller。重要的是,table view controller也是fetched results controller的delegate,因此当有数据变化时,他可以被回调。

然后,你通过performFetch:方法来启动NSFetchedResultsController

Integrating the Fetched Results Controller with the Table View Data Source

在你初始化完成并且有数据需要展示在table view的时候,你需要将fetched results controller同table view data source UITableViewDataSource归整为一。

objc

  1. #pragma mark - UITableViewDataSource
  2.  
  3. - (void)configureCell:(id)cellatIndexPath:(NSIndexPath*)indexPath
  4. {
  5. id object= [[self fetchedResultsController] objectAtIndexPath:indexPath];
  6.  
  7. // Populate cell from the NSManagedObject instance
  8. }
  9.  
  10. - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
  11. {
  12. id cell= [tableViewdequeueReusableCellWithIdentifier:CellReuseIdentifier];
  13. // Set up the cell
  14. [self configureCell:cell atIndexPath:indexPath];
  15. return cell;
  16. }
  17.  
  18. - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
  19. {
  20. return [[[selffetchedResultsController] sections] count];
  21. }
  22.  
  23. - (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
  24. {
  25. id< NSFetchedResultsSectionInfo> sectionInfo= [[self fetchedResultsController] sections][section];
  26. return [sectionInfonumberOfObjects];
  27. }

swift

  1. func configureCell(cell:UITableViewCell, indexPath: NSIndexPath) {
  2. guard letselectedObject = fetchedResultsController.objectAtIndexPath(indexPath)as? AAAEmployeeMO else { fatalError("Unexpected Object in FetchedResultsController") }
  3. // Populate cell from the NSManagedObject instance
  4. print("Object for configuration:\(object)")
  5. }
  6.  
  7. override functableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  8. let cell =tableView.dequeueReusableCellWithIdentifier("cellIdentifier",forIndexPath: indexPath)
  9. // Set up the cell
  10. configureCell(cell,indexPath: indexPath)
  11. return cell
  12. }
  13.  
  14. override funcnumberOfSectionsInTableView(tableView:UITableView) -> Int {
  15. return fetchedResultsController.sections!.count
  16. }
  17.  
  18. override functableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  19. guard letsections = fetchedResultsController.sectionselse {
  20. fatalError("No sections in fetchedResultsController")
  21. }
  22. let sectionInfo =sections[section]
  23. return sectionInfo.numberOfObjects
  24. }

正如在如上的UITableViewDataSource方法中所展示的,fetched results controller和table view的关联都设计为单一的方法调用来完成。

Communicating Data Changes to the Table View

NSFetchedResultsController还掌控了当有数据变化时,同UITableViewController的通讯。实现NSFetchedResultsControllerDelegate即可

objc

  1. #pragma mark - NSFetchedResultsControllerDelegate
  2. - (void)controllerWillChangeContent:(NSFetchedResultsController*)controller
  3. {
  4. [[selftableView] beginUpdates];
  5. }
  6. - (void)controller:(NSFetchedResultsController*)controllerdidChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfoatIndex:(NSUInteger)sectionIndexforChangeType:(NSFetchedResultsChangeType)type
  7. {
  8. switch(type){
  9. case NSFetchedResultsChangeInsert:
  10. [[selftableView] insertSections:[NSIndexSetindexSetWithIndex:sectionIndex]withRowAnimation:UITableViewRowAnimationFade];
  11. break;
  12. case NSFetchedResultsChangeDelete:
  13. [[selftableView] deleteSections:[NSIndexSetindexSetWithIndex:sectionIndex]withRowAnimation:UITableViewRowAnimationFade];
  14. break;
  15. case NSFetchedResultsChangeMove:
  16. case NSFetchedResultsChangeUpdate:
  17. break;
  18. }
  19. }
  20. - (void)controller:(NSFetchedResultsController*)controllerdidChangeObject:(id)anObjectatIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)typenewIndexPath:(NSIndexPath*)newIndexPath
  21. {
  22. switch(type){
  23. case NSFetchedResultsChangeInsert:
  24. [[selftableView] insertRowsAtIndexPaths:@[newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
  25. break;
  26. case NSFetchedResultsChangeDelete:
  27. [[selftableView] deleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationFade];
  28. break;
  29. case NSFetchedResultsChangeUpdate:
  30. [self configureCell:[[self tableView] cellForRowAtIndexPath:indexPath]atIndexPath:indexPath];
  31. break;
  32. case NSFetchedResultsChangeMove:
  33. [[selftableView] deleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationFade];
  34. [[selftableView] insertRowsAtIndexPaths:@[newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
  35. break;
  36. }
  37. }
  38. - (void)controllerDidChangeContent:(NSFetchedResultsController*)controller
  39. {
  40. [[selftableView] endUpdates];
  41. }

swift

  1. func controllerWillChangeContent(controller:NSFetchedResultsController) {
  2. tableView.beginUpdates()
  3. }
  4.  
  5. func controller(controller:NSFetchedResultsController, didChangeSectionsectionInfo: NSFetchedResultsSectionInfo,atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
  6. switch type {
  7. case .Insert:
  8. tableView.insertSections(NSIndexSet(index:sectionIndex), withRowAnimation: .Fade)
  9. case .Delete:
  10. tableView.deleteSections(NSIndexSet(index:sectionIndex), withRowAnimation: .Fade)
  11. case .Move:
  12. break
  13. case .Update:
  14. break
  15. }
  16. }
  17.  
  18. func controller(controller:NSFetchedResultsController, didChangeObjectanObject: AnyObject, atIndexPath indexPath: NSIndexPath?,forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
  19. switch type {
  20. case .Insert:
  21. tableView.insertRowsAtIndexPaths([newIndexPath!],withRowAnimation: .Fade)
  22. case .Delete:
  23. tableView.deleteRowsAtIndexPaths([indexPath!],withRowAnimation: .Fade)
  24. case .Update:
  25. configureCell(tableView.cellForRowAtIndexPath(indexPath!)!,indexPath: indexPath!)
  26. case .Move:
  27. tableView.moveRowAtIndexPath(indexPath!,toIndexPath: newIndexPath!)
  28. }
  29. }
  30.  
  31. func controllerDidChangeContent(controller:NSFetchedResultsController) {
  32. tableView.endUpdates()
  33. }

Adding Sections

目前为止,table view只有一个section,如果需要使用多个Employee对象,可以划分多个section。

objc

  1. - (void)initializeFetchedResultsController
  2. {
  3. NSFetchRequest *request = [NSFetchRequestfetchRequestWithEntityName:@"Person"];
  4. NSSortDescriptor *departmentSort = [NSSortDescriptor sortDescriptorWithKey:@"department.name"ascending:YES];
  5. NSSortDescriptor *lastNameSort = [NSSortDescriptor sortDescriptorWithKey:@"lastName"ascending:YES];
  6. [requestsetSortDescriptors:@[departmentSort,lastNameSort]];
  7. NSManagedObjectContext *moc = [[selfdataController] managedObjectContext];
  8. [self setFetchedResultsController:[[NSFetchedResultsControlleralloc] initWithFetchRequest:requestmanagedObjectContext:moc sectionNameKeyPath:@"department.name" cacheName:nil]];
  9. [[selffetchedResultsController] setDelegate:self];

swift

  1. func initializeFetchedResultsController() {
  2. let request =NSFetchRequest(entityName: "Person")
  3. let departmentSort =NSSortDescriptor(key: "department.name", ascending: true)
  4. let lastNameSort =NSSortDescriptor(key: "lastName", ascending: true)
  5. request.sortDescriptors = [departmentSort,lastNameSort]
  6. let moc =dataController.managedObjectContext
  7. fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc,sectionNameKeyPath: "department.name",cacheName: nil)
  8. fetchedResultsController.delegate =self
  9. do {
  10. try fetchedResultsController.performFetch()
  11. } catch {
  12. fatalError("Failed to initialize FetchedResultsController:\(error)")
  13. }
  14. }

这个例子中你为NSFetchRequest实例添加了一个NSSortDescriptor实例。fetched results controller使用这个初始化排序controller来将数据分隔为不同的sections,因此需要keys来匹配。

这个变化使得fetched results controller将Person实例来分隔为多个sections。唯一的条件是:

  • sectionNameKeyPath属性必须也是一个NSSortDescriptor实例。

  • NSSortDescriptor必须是数组中的第一个descriptor被传递给fetch request。

Adding Caching for Performance

大多数情况下,table view会展示相对固定的数据。在整个程序的运行周期内,创建table view controller时的fetch request不会发生变化。使用NSFetchedResultsController添加缓存可以在程序再次启动的时候而且数据不发生改变,table view会即刻初始化。这个缓存对于大数据尤为有用。

  1. [self setFetchedResultsController:[[NSFetchedResultsControlleralloc] initWithFetchRequest:requestmanagedObjectContext:moc sectionNameKeyPath:@"department.name" cacheName:@"rootCache"]];
  1. fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc,sectionNameKeyPath: "department.name",cacheName: "rootCache")

如上这样后续的数据加载就可以一瞬间完成。

注意:如果数据改变了,那么你如果需要清除缓存就直接调用deleteCacheWithName:即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值