NSFetchedResultsController 用于在 Apple Watch 上显示记录?
Posted
技术标签:
【中文标题】NSFetchedResultsController 用于在 Apple Watch 上显示记录?【英文标题】:NSFetchResultController for showing records on an Apple Watch? 【发布时间】:2015-04-08 07:38:21 【问题描述】:我可以在 Apple Watch 上使用NSFetchResultController
在表格中显示 80 到 90 条记录吗?
我使用WKInterfaceTable+IGInterfaceDataTable
来使用数据源类型加载方法,因为在我看来这比使用NSArray
简单。
NSFetchResultController
会有助于提高效率还是会降低效率?
【问题讨论】:
【参考方案1】:我发现 NSFetchResultController 在 iWatch 应用程序中根本没有用,因为 WKInterfaceTable 不支持对 NSFetchResultController 在委托中支持的单行进行编辑、更改或删除的委托方法。所以你每次都必须更新你想要显示的所有数据,所以我认为我们不应该使用它。
【讨论】:
但它使表格的排序变得容易。【参考方案2】:我在 Apple Watch 应用程序中使用了 NSFetchedResultController
和 WKInterfaceTable
。确实不如UITableViewController
方便,但是非常可行。我没有任何性能问题,即使在加载 20+ 行时(没有尝试 80-90)。当然这是在模拟器中,所以我不知道设备本身会如何表现。
插入、更新和删除你必须自己实现,但没那么难。
下面是我在InterfaceController中的部分代码,以插入行为例,但编辑和删除并不难:
界面
...
@property (weak, nonatomic) IBOutlet WKInterfaceTable *interfaceTable;
@property(strong, nonatomic) NSFetchRequest *fetchRequest;
@property(strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
@property(strong, nonatomic) NSMutableArray *data;
...
实施
获取和往常一样,只是我们没有为结果控制器分配委托,而是直接保存数据:
self.fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"YourModel" inManagedObjectContext:self.managedObjectContext];
self.fetchRequest.entity = entityDescription;
[self.fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:YES]]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
[self.fetchedResultsController performFetch:&error];
self.data= self.fetchedResultsController.fetchedObjects;
然后我使用一个函数loadTableData
:
- (void)loadTableData
[self.interfaceTable setNumberOfRows:[[self data] count] withRowType:@"YourCustomCell"];
[self.interfaceTable insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:[[self data] count]] withRowType:@"YourRowType"];
for (int i = 0; i<[[self data] count];i++)
[self configureRowControllerAtIndex:i];
调用configureRowControllerAtIndex
,一个填充一行的函数(我有两个标签):
- (void)configureRowControllerAtIndex:(NSInteger)index
WKTableVIewRowController *listItemRowController = [self.interfaceTable rowControllerAtIndex:index];
[listItemRowController setTitle:[[self.data[index] title] integerValue]];
[listItemRowController setDescription:[self.data[index] description]];
插入新行时,只需在数据数组中手动添加managedObjectContext
和:
// Add in managedObjectContext
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"YourModel" inManagedObjectContext:self.managedObjectContext];
YourModel *newRow = [[YourModel alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:nil];
// Add in data array
[self.data addObject:newRow];
并定期保存 managedObjectContext:
if (![self.managedObjectContext save:&error])
if (error)
NSLog(@"Unable to save changes.");
NSLog(@"%@, %@", error, error.localizedDescription);
【讨论】:
如何处理 NSFetchResultControllerDelegates 的回调方法?我认为即使添加单个项目,您也需要计算所有行和其他内容,因为 iWatch 为表格显示一次屏幕,而要进行一次更改,您需要再次加载所有表格数据。 现在我在插入、更新、删除后重新加载表,是的。不过,您可以使用configureRowControllerAtIndex
更新现有行(见上文)。您想使用哪些回调方法? didChangeObject: atIndexPath
等等,您可以在运行 configureRowControllerAtIndex
之后通过执行块(在单独的线程上)来替换。这在 Watch 应用中运行良好。【参考方案3】:
让NSFetchedResultsController
与WKInterfaceTable
一起工作是一个PITA。地狱,将普通数组/数据字典映射到WKInterfaceTable
很糟糕。我们构建并开源了一个简单的库来简化此操作,至少使 API 类似于UITableView
。刚刚获得了一些外部帮助,增加了对 NSFetchedResultsController
的支持。希望这对未来有帮助!
https://github.com/Instagram/IGInterfaceDataTable
【讨论】:
以上是关于NSFetchedResultsController 用于在 Apple Watch 上显示记录?的主要内容,如果未能解决你的问题,请参考以下文章