我的应用程序调用核心数据并使用nsfetchedresultscontroller管理对象,并使用结果构建tableview。点击时的tableview单元格推送到详细视图,我可以在其中更改对象的属性并保存。
- (void)viewDidLoad {
[super viewDidLoad];
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Failed to fetch data");
}
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.entity = [NSEntityDescription entityForName:@"ZTExercise" inManagedObjectContext:[[ZTDataManager sharedDataManager] mainContext]];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[ZTDataManager sharedDataManager].mainContext sectionNameKeyPath:@"sectionTitle" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"detailExerciseSegue"]) {
ZTExerciseDetailController *controller = segue.destinationViewController;
NSIndexPath *selectedIndexPath;
ZTExercise *exercise;
if (self.searchDisplayController.isActive) {
selectedIndexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
exercise = self.searchResults.allValues[selectedIndexPath.section][selectedIndexPath.row];
} else {
selectedIndexPath = [self.tableView indexPathForSelectedRow];
exercise = [self.fetchedResultsController objectAtIndexPath:selectedIndexPath];
}
controller.exercise = exercise;
}
}
在tableview控制器中,还有一个搜索栏,在点击单元格时会将对象推到同一个视图。
触发崩溃的操作是
[self applyCustomizationToAlertView:[ZTAlertView showAlertWithTitle:@"Add record" message:@"Enter new lifting weight (lbs)" cancelTitle:@"Cancel" otherTitle:@"Add" contentView:addRecordView completion:^(BOOL cancelled, NSInteger buttonIndex) {
if (cancelled) {
return;
}
if (buttonIndex == 1) {
if (addRecordTextField.text && [addRecordTextField.text length]) {
ZTExerciseRecord *newRecord = [ZTExerciseRecord insertObjectInContext:[ZTDataManager sharedDataManager].mainContext];
newRecord.score = [addRecordTextField.text integerValue];
[self.exercise insertObject:newRecord inERecordsAtIndex:0];
NSError *error;
if (![[ZTDataManager sharedDataManager].mainContext save:&error]) {
NSLog(@"Failed to save data");
return;
}
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:[self.sections indexOfObject:ZTSectionNameLift]]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
return;
}
}
}]];
和
self.exercise.eRecords = [NSOrderedSet orderedSetWithArray:[self.exercise.eRecords sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"dateCreated" ascending:NO]]]];
当我通过搜索栏搜索对象时,如果点击的单元格不是searchtableview的第一个条目,则会发生崩溃。它推送到详细视图,但是当我执行涉及更改关系或保存上下文的操作时,它会使用此代码崩溃
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. *** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0] with userInfo (null)
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
感谢所有帮助, 提前谢谢。
更新1 错误说我在索引1处插入了一些内容,但在我的所有代码中,访问0以外索引的唯一部分是在表viewdata源中,这与获取的对象数一致。
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (self.recordTableView == tableView) {
return 1;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.recordTableView == tableView) {
return [self.exercise.eRecords count];
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier;
UITableViewCell *cell;
if (self.recordTableView == tableView) {
cellIdentifier = @"ZTExerciseLogCell";
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[ZTExerciseLogCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
if ([cell.reuseIdentifier isEqualToString:@"ZTExerciseLogCell"]) {
ZTExerciseLogCell *newCell = (ZTExerciseLogCell *)cell;
newCell.record = self.exercise.eRecords[indexPath.row];
}
}
ZTExerciseController - >推 - > ZTExerciseDetailController
我注意到的另一件事是在名为ZTExerciseDetailController的类中发生错误但在崩溃日志中错误表明它发生在ZTExerciseController
此崩溃日志属于在练习的mutableorderedset中插入对象
*** First throw call stack:
(
0 CoreFoundation 0x0000000101cc3495 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001017c399e objc_exception_throw + 43
2 CoreFoundation 0x0000000101c7be3f -[__NSArrayI objectAtIndex:] + 175
3 ZetaProject 0x0000000100004524 -[ZTExerciseController configureCell:atIndexPath:] + 404
4 ZetaProject 0x0000000100005a13 -[ZTExerciseController controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:] + 819
5 CoreData 0x0000000102047c3b -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 4187
6 CoreFoundation 0x0000000101d18d9c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
7 CoreFoundation 0x0000000101c7b51d _CFXNotificationPost + 2381
8 Foundation 0x00000001001547fa -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
9 CoreData 0x0000000101f7348a -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 74
10 CoreData 0x0000000101ff9c8b -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] + 331
11 CoreData 0x0000000101f6f243 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 1875
12 CoreData 0x0000000101ff9d25 __90-[NSManagedObjectContext(_NSInternalNotificationHandling) _processEndOfEventNotification:]_block_invoke + 85
13 CoreData 0x0000000101f90c7b developerSubmittedBlockToNSManagedObjectContextPerform + 107
14 CoreData 0x0000000101f90bc4 -[NSManagedObjectContext performBlockAndWait:] + 132
15 CoreData 0x0000000101f9364b -[NSManagedObjectContext(_NSInternalNotificationHandling) _processEndOfEventNotification:] + 123
16 CoreFoundation 0x0000000101d18d9c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
17 CoreFoundation 0x0000000101c7b51d _CFXNotificationPost + 2381
18 Foundation 0x00000001001547fa -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
19 Foundation 0x0000000100149460 -[NSUndoManager _postCheckpointNotification] + 92
20 Foundation 0x0000000100149242 -[NSUndoManager _endUndoGroupRemovingIfEmpty:] + 95
21 Foundation 0x00000001001985ff __NSFirePerformWithOrder + 339
22 CoreFoundation 0x0000000101c8edc7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
23 CoreFoundation 0x0000000101c8ed37 __CFRunLoopDoObservers + 391
24 CoreFoundation 0x0000000101c6e438 __CFRunLoopRun + 712
25 CoreFoundation 0x0000000101c6dd83 CFRunLoopRunSpecific + 467
26 GraphicsServices 0x0000000103471f04 GSEventRunModal + 161
27 UIKit 0x000000010059fe33 UIApplicationMain + 1010
28 ZetaProject 0x000000010002a6a3 main + 115
29 libdyld.dylib 0x00000001030f35fd start + 1
)
更新2
好的,我认为已经解决了这个问题。当对运动对象进行更改时,它显然会调用NSFetchedResultsControllerDelegate(Update type)函数:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray
arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
然后它调用configureCell:atIndexPath:function:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
ZTExerciseCell *newCell = (ZTExerciseCell *)cell;
ZTExercise *exercise;
if (self.searchDisplayController.isActive && [self.searchResults count]) {
exercise = self.searchResults.allValues[indexPath.section][indexPath.row];
} else {
exercise = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
newCell.exercise = exercise;
}
但问题是在此期间搜索表视图处于活动状态并获取错误的对象。如何验证何时来自委托获取结果函数或tableviewcell函数?还是有更好的方法来使用nsfetchresultscontroller操作搜索表视图?
答案 0 :(得分:0)
第二行日志表示您正在尝试访问不存在的数组索引。也许您忘记初始化它或其他东西。 检查XCode 5: How to Debug? Get the line of the error? NSInvalidArgumentException并跟踪代码崩溃的哪一行
答案 1 :(得分:0)
NSFetchedResultsController * consultMessageFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[[[WYCoreDataStorage shareStore] coreDataHelper] mainContext] sectionNameKeyPath:nil cacheName:entityName];
cacheName:entityName 这个设置了cache,导致的,如果设置了,一定要不用的时候移除掉
。
苹果文档如下:: 重要强> 如果使用缓存,则必须在更改任何获取请求,其谓词或其排序描述符之前调用deleteCacheWithName :.除非将cacheName设置为nil,否则不得为多个查询重用相同的获取结果控制器。