【发布时间】:2016-02-20 11:29:00
【问题描述】:
我有一个简单的应用程序,每个 UITabBar 中有一个 UITabBarController 和 2 个 UITableViewControllers。第一个UITableViewController 称为Videos,第二个称为Languages。
Videos 将仅代表具有视频的语言,Languages 将显示所有语言。
出于测试目的,我从 AppDelegate 填充核心数据实体。
我的核心数据模型如下:
填充核心数据的方法如下所示:
- (void)loadVideosTab
{
// Here is where we'll load up the Videos tab.
NSManagedObjectContext *context = [self managedObjectContext];
NSString *chinese = @"Chinese";
NSString *dutch = @"Dutch";
NSString *english = @"English";
NSString *french = @"French";
NSString *italian = @"Italian";
NSString *punjabi = @"Punjabi";
NSString *spanish = @"Spanish";
NSString *tamil = @"Tamil - தமிழ்";
Language *language = [NSEntityDescription insertNewObjectForEntityForName:@"Language" inManagedObjectContext:context];
Video *chineseLanguage = (Video *)[Video videoLanguage:chinese inManagedObjectContext:context];
language.videos = chineseLanguage;
Video *dutchLanguage = (Video *)[Video videoLanguage:dutch inManagedObjectContext:context];
language.videos = dutchLanguage;
Video *englishLanguage = (Video *)[Video videoLanguage:english inManagedObjectContext:context];
language.videos = englishLanguage;
Video *frenchLanguage = (Video *)[Video videoLanguage:french inManagedObjectContext:context];
language.videos = frenchLanguage;
Video *italianLanguage = (Video *)[Video videoLanguage:italian inManagedObjectContext:context];
language.videos = italianLanguage;
Video *punjabiLanguage = (Video *)[Video videoLanguage:punjabi inManagedObjectContext:context];
language.videos = punjabiLanguage;
Video *spanishLanguage = (Video *)[Video videoLanguage:spanish inManagedObjectContext:context];
language.videos = spanishLanguage;
Video *tamilLanguage = (Video *)[Video videoLanguage:tamil inManagedObjectContext:context];
language.videos = tamilLanguage;
NSError *error = nil;
if (![context save:&error])
{
// Error
}
}
我在 Video 实体上调用的类别是:
+ (Video *)videoLanguage:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context
{
Video *video = nil;
// Creating a fetch request to check whether the video already exists, calling from the AppDelegate
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Video"];
request.predicate = [NSPredicate predicateWithFormat:@"language = %@", name];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"language" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *videoTitles = [context executeFetchRequest:request error:&error];
if (!videoTitles)
{
// Handle Error
}
else if (![videoTitles count])
{
// If the video count is 0 then create it
video = [NSEntityDescription insertNewObjectForEntityForName:@"Video" inManagedObjectContext:context];
video.language = name;
}
else
{
// If the object exists, just return it
video = [videoTitles lastObject];
}
return video;
}
所以在Video 标签中,我使用的是NSFetchedResultsController:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Video" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
NSPredicate *d = [NSPredicate predicateWithFormat:@"language != nil"];
[fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"language" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
cellForRow 是:
VideoTabTableViewCell *customCell = (VideoTabTableViewCell *)cell;
Video *video = [self.fetchedResultsController objectAtIndexPath:indexPath];
customCell.videoTabCellLabel.text = video.language;
customCell.videoTabCellLabel.textColor = [UIColor whiteColor];
这成功地引入了语言。
现在,出于测试目的,我希望“语言”选项卡执行完全相同的操作。我有一个Language 实体的原因是“语言”选项卡将是具有视频和传单的语言的组合。
所以在Languages 标签中,我的fetchedResultsController 是:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Language" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
// NSPredicate *d = [NSPredicate predicateWithFormat:@"name != nil"];
// [fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"videos.language" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
cellForRow 是:
VideoTabTableViewCell *customCell = (VideoTabTableViewCell *)cell;
Language *languages = [self.fetchedResultsController objectAtIndexPath:indexPath];
customCell.videoTabCellLabel.text = languages.videos.language;
customCell.videoTabCellLabel.textColor = [UIColor whiteColor];
更新 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"语言标签";
VideoTabTableViewCell *cell = (VideoTabTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.languagesTabTableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
// The boiler plate code for the NSFetchedResultsControllerDelegate
UITableView *tableView = self.languagesTabTableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.languagesTabTableView endUpdates];
}
我从viewDidLoad 调用fetchedResultsController 并从viewWillAppear 重新加载表。
但是,Languages 选项卡上的情况是它只显示我添加的最后一种语言,并且每次启动时,我都会创建另一个新的空单元格。
我只是无法弄清楚这到底是怎么回事。
澄清一下,这里的主要问题不是幻影细胞,而是为什么语言只拾取最后一个条目而不是其他条目。
任何指导将不胜感激。
【问题讨论】:
-
几个 cmets:1. 我在 cellforrowatindex 处缺少出队... 2. 单元格是否可能是空的,因为它们为空 3. 您是否缺少 NSFetchedResultsController 中的数据或它只是没有显示 4. 放一些 nslogs 并检查上述内容,并在相关区域放置一些断点并执行 po
-
非常感谢@RoyFalk 的回复 - 我很感激。我没有完全展示单元格的代码(对此感到抱歉)和 NSFRC 也是如此。我在更新中提供了这一点。我用languages.videos.language 在cellForRow 中放置了一个NSLog,结果是NULL、NULL,然后是泰米尔语。此类与“视频”选项卡具有相同的代码,除了 NSFRC 不同并且 cellForRow 指向 language.video.language 而不是 video.language..
标签: ios iphone uitableview core-data nsfetchedresultscontroller