我尝试将TopSongs解析器和核心数据文件添加到我的应用程序中,现在它已成功构建,没有错误或警告消息。但是,只要应用程序加载,它就会崩溃,原因如下:
更新:我已经完成了所有工作,但我的TableView没有显示任何数据,并且应用程序不响应以下断点。
感谢。
更新:这是不响应断点的新代码。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)table {
return [[fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.tableView = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext];
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellIdentifier = @"SongCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
}
Incident *incident = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"#%d %@", @"#%d %@"), incident.title];
return cell;
}
- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[table deselectRowAtIndexPath:indexPath animated:YES];
self.detailController.incident = [fetchedResultsController objectAtIndexPath:indexPath];
[self.navigationController pushViewController:self.detailController animated:YES];
}
更新:这是找到所有fetch实例的代码。
- (Category *)categoryWithName:(NSString *)name {
NSTimeInterval before = [NSDate timeIntervalSinceReferenceDate];
#ifdef USE_CACHING
// check cache
CacheNode *cacheNode = [cache objectForKey:name];
if (cacheNode != nil) {
// cache hit, update access counter
cacheNode.accessCounter = accessCounter++;
Category *category = (Category *)[managedObjectContext objectWithID:cacheNode.objectID];
totalCacheHitCost += ([NSDate timeIntervalSinceReferenceDate] - before);
cacheHitCount++;
return category;
}
#endif
// cache missed, fetch from store - if not found in store there is no category object for the name and we must create one
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:self.categoryEntityDescription];
NSPredicate *predicate = [self.categoryNamePredicateTemplate predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:name forKey:kCategoryNameSubstitutionVariable]];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *fetchResults = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
NSAssert1(fetchResults != nil, @"Unhandled error executing fetch request in import thread: %@", [error localizedDescription]);
Category *category = nil;
if ([fetchResults count] > 0) {
// get category from fetch
category = [fetchResults objectAtIndex:0];
} else if ([fetchResults count] == 0) {
// category not in store, must create a new category object
category = [[Category alloc] initWithEntity:self.categoryEntityDescription insertIntoManagedObjectContext:managedObjectContext];
category.name = name;
[category autorelease];
}
#ifdef USE_CACHING
// add to cache
// first check to see if cache is full
if ([cache count] >= cacheSize) {
// evict least recently used (LRU) item from cache
NSUInteger oldestAccessCount = UINT_MAX;
NSString *key = nil, *keyOfOldestCacheNode = nil;
for (key in cache) {
CacheNode *tmpNode = [cache objectForKey:key];
if (tmpNode.accessCounter < oldestAccessCount) {
oldestAccessCount = tmpNode.accessCounter;
[keyOfOldestCacheNode release];
keyOfOldestCacheNode = [key retain];
}
}
// retain the cache node for reuse
cacheNode = [[cache objectForKey:keyOfOldestCacheNode] retain];
// remove from the cache
[cache removeObjectForKey:keyOfOldestCacheNode];
} else {
// create a new cache node
cacheNode = [[CacheNode alloc] init];
}
cacheNode.objectID = [category objectID];
cacheNode.accessCounter = accessCounter++;
[cache setObject:cacheNode forKey:name];
[cacheNode release];
#endif
totalCacheMissCost += ([NSDate timeIntervalSinceReferenceDate] - before);
cacheMissCount++;
return category;
}
这一个......
- (void)fetch {
NSError *error = nil;
BOOL success = [self.fetchedResultsController performFetch:&error];
NSAssert2(success, @"Unhandled error performing fetch at SongsViewController.m, line %d: %@", __LINE__, [error localizedDescription]);
[self.tableView reloadData];
}
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Song" inManagedObjectContext:managedObjectContext]];
NSArray *sortDescriptors = nil;
NSString *sectionNameKeyPath = nil;
if ([fetchSectioningControl selectedSegmentIndex] == 1) {
sortDescriptors = [NSArray arrayWithObjects:[[[NSSortDescriptor alloc] initWithKey:@"category.name" ascending:YES] autorelease], [[[NSSortDescriptor alloc] initWithKey:@"rank" ascending:YES] autorelease], nil];
sectionNameKeyPath = @"category.name";
} else {
sortDescriptors = [NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"rank" ascending:YES] autorelease]];
}
[fetchRequest setSortDescriptors:sortDescriptors];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:sectionNameKeyPath cacheName:@"SongsCache"];
}
return fetchedResultsController;
}
答案 0 :(得分:0)
基于发布的代码和问题描述,我怀疑categoryEntityDescription
属性返回nil。
答案 1 :(得分:0)
您的额外缓存可能会浪费周期,因为Core Data会在内部执行自己的缓存。我愿意打赌你放慢速度而不是加快速度,更不用说你正在消耗的额外内存。
您在哪里设置categoryEntityDescription
?现在显示在您发布的代码中。这可能是零。
为什么要保留NSEntityDescription
?!?它们已经因为核心数据而处于内存状态,如果Core Data希望在某些时候发布它,那么保留它们可能会导致问题。
您的缓存绝对不是来自Apple的代码,因为他们知道缓存是在Core Data中。
对于NSEntityDescription
,再次 保留NSEntityDescription
。
您是否100%肯定NSEntityDescription
不是零?你在调试器中确认了吗?您是否使用刚刚检索过的NSEntityDescription
?
您需要学习使用调试器,因为这将解决您的大多数编码问题。在此方法中放置一个断点并在调试器中运行代码。然后,当执行在该断点处停止时,您可以检查变量的值并了解它们当前设置的内容。这将证实或否认你对什么是和不是的怀疑。
当您未能在Entity
中设置NSFetchRequest
时,您会看到此错误,根据您的代码,这意味着在您显示的代码出现之前未设置保留属性调用。
答案 2 :(得分:0)
由于您手动添加了模型文件,因此目标中Compile Sources步骤中的.xcdatamodel文件是什么?
转到群组&amp;中的目标条目Xcode中的文件窗格,然后单击显示三角形。然后单击您的应用程序的显示三角形。然后检查它是否在Compile Sources中。如果没有,请右键单击Compile Sources并选择“Add - &gt; Existing File ...”并添加它。
根据更新进行修改:
更新:这是新代码 没有回应断点。
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath
您的视图控制器是否设置为UITableViewDataSource
的{{1}} / UITableViewDelegate
?如果没有,这些方法将不会被调用。
答案 3 :(得分:0)
我已经看到,当提取请求的NSEntityDescription
为零时会发生这种情况。最可能的原因是您的模型实体的名称与您提供给entityForName
的名称不同。除此之外,它可能是配置Core Data堆栈或缺少数据模型时出错,但作为第一步,我建议将entityForName
的结果存储在局部变量中并在那里确保它不是零。