coredata学习总结(六)

来源:互联网 发布:北京方便面的危害知乎 编辑:程序博客网 时间:2024/06/04 23:27

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. - (void)initializeFetchedResultsController
  3. {
  4. NSFetchRequest *request = [NSFetchRequestfetchRequestWithEntityName:@"Person"];

  5. NSSortDescriptor *lastNameSort = [NSSortDescriptor sortDescriptorWithKey:@"lastName"ascending:YES];

  6. [requestsetSortDescriptors:@[lastNameSort]];

  7. NSManagedObjectContext *moc = ;//Retrieve the main queue NSManagedObjectContext

  8. [self setFetchedResultsController:[[NSFetchedResultsControlleralloc]initWithFetchRequest:requestmanagedObjectContext:mocsectionNameKeyPath:nil cacheName:nil]];
  9. [[selffetchedResultsController]setDelegate:self];

  10. NSError *error=nil;
  11. if (![[selffetchedResultsController]performFetch:&error]){
  12. NSLog(@"Failed to initialize FetchedResultsController: %@\n%@",[errorlocalizedDescription],[erroruserInfo]);
  13. abort();
  14. }
  15. }
  1. var fetchedResultsController:NSFetchedResultsController!

  2. func initializeFetchedResultsController() {
  3. let request =NSFetchRequest(entityName:"Person")
  4. let departmentSort =NSSortDescriptor(key:"department.name", ascending: true)
  5. let lastNameSort =NSSortDescriptor(key:"lastName", ascending: true)
  6. request.sortDescriptors = [departmentSort,lastNameSort]

  7. let moc =dataController.managedObjectContext
  8. fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc,sectionNameKeyPath:"department.name",cacheName: "rootCache")
  9. fetchedResultsController.delegate =self

  10. do {
  11. try fetchedResultsController.performFetch()
  12. } catch {
  13. fatalError("Failed to initialize FetchedResultsController:\(error)")
  14. }
  15. }

首先要构造一个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. - (void)configureCell:(id)cellatIndexPath:(NSIndexPath*)indexPath
  3. {
  4. id object=[[self fetchedResultsController]objectAtIndexPath:indexPath];

  5. // Populate cell from the NSManagedObject instance
  6. }

  7. - (UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath
  8. {
  9. id cell=[tableViewdequeueReusableCellWithIdentifier:CellReuseIdentifier];
  10. // Set up the cell
  11. [self configureCell:cell atIndexPath:indexPath];
  12. return cell;
  13. }

  14. - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
  15. {
  16. return [[[selffetchedResultsController]sections] count];
  17. }

  18. - (NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section
  19. {
  20. id< NSFetchedResultsSectionInfo> sectionInfo=[[self fetchedResultsController]sections][section];
  21. return [sectionInfonumberOfObjects];
  22. }

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. override functableView(tableView:UITableView, cellForRowAtIndexPathindexPath: NSIndexPath) -> UITableViewCell {
  7. let cell =tableView.dequeueReusableCellWithIdentifier("cellIdentifier",forIndexPath:indexPath)
  8. // Set up the cell
  9. configureCell(cell,indexPath:indexPath)
  10. return cell
  11. }

  12. override funcnumberOfSectionsInTableView(tableView:UITableView) ->Int {
  13. return fetchedResultsController.sections!.count
  14. }

  15. override functableView(tableView:UITableView, numberOfRowsInSectionsection: Int) -> Int {
  16. guard letsections =fetchedResultsController.sectionselse {
  17. fatalError("No sections in fetchedResultsController")
  18. }
  19. let sectionInfo =sections[section]
  20. return sectionInfo.numberOfObjects
  21. }

正如在如上的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*)indexPathforChangeType:(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. func controller(controller:NSFetchedResultsController,didChangeSectionsectionInfo: NSFetchedResultsSectionInfo,atIndex sectionIndex: Int, forChangeTypetype: NSFetchedResultsChangeType) {
  5. switch type {
  6. case .Insert:
  7. tableView.insertSections(NSIndexSet(index:sectionIndex),withRowAnimation: .Fade)
  8. case .Delete:
  9. tableView.deleteSections(NSIndexSet(index:sectionIndex),withRowAnimation: .Fade)
  10. case .Move:
  11. break
  12. case .Update:
  13. break
  14. }
  15. }

  16. func controller(controller:NSFetchedResultsController,didChangeObjectanObject: AnyObject, atIndexPath indexPath:NSIndexPath?,forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
  17. switch type {
  18. case .Insert:
  19. tableView.insertRowsAtIndexPaths([newIndexPath!],withRowAnimation: .Fade)
  20. case .Delete:
  21. tableView.deleteRowsAtIndexPaths([indexPath!],withRowAnimation: .Fade)
  22. case .Update:
  23. configureCell(tableView.cellForRowAtIndexPath(indexPath!)!,indexPath:indexPath!)
  24. case .Move:
  25. tableView.moveRowAtIndexPath(indexPath!,toIndexPath:newIndexPath!)
  26. }
  27. }

  28. func controllerDidChangeContent(controller:NSFetchedResultsController) {
  29. tableView.endUpdates()
  30. }
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:mocsectionNameKeyPath:@"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:mocsectionNameKeyPath:@"department.name"cacheName:@"rootCache"]];
  1. fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc,sectionNameKeyPath:"department.name",cacheName: "rootCache")

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

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

0 0
原创粉丝点击