gpt4 book ai didi

objective-c - 保存列出的对象之一后 NSFetchedResultsController 损坏排序

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:25:05 24 4
gpt4 key购买 nike

我有一组用于 CoreData 浏览的通用 View /类,但在保存对所列对象之一的属性的更改后,我的获取结果 Controller 的排序顺序出现问题。

在我的 TableView Controller 的 viewWillAppear: 中,我这样设置了我的获取结果 Controller :

- (void) setupFetchedResultsController {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: self.entityToList];
request.predicate = self.entitySelectionPredicate; // Typically nil
request.sortDescriptors = self.entitySortDescriptorList;
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest: request
managedObjectContext: self.contextForEntity
sectionNameKeyPath: self.keyPathForSections
cacheName: nil]; /* Not chacheing */
}

在这个 TableView Controller 的 didSelectRowAtIndexPath 中,我推送到一个详细的 TableView Controller ,如下所示:

- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
id objectInCell = [self.fetchedResultsController objectAtIndexPath: indexPath];
ManagedObjectDetailTableViewController *dvc = [[ManagedObjectDetailTableViewController alloc]
initWithStyle: UITableViewStyleGrouped];
dvc.detailItem = objectInCell;
[self.navigationController pushViewController: dvc animated: YES];
}

ManagedObjectDetailTableViewController 的每个属性和每个关系都有一行。在 didSelectRowAtIndexPath 中,如果选择了包含和属性的行,我将推送到 ManagedObjectAttributeEditViewController View Controller :

- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
// Section 0 has the attributes for the 'detailItem' object alphabetically by name
if( indexPath.section == 0 ) {
ManagedObjectAttributeEditViewController *evc = [[ManagedObjectAttributeEditViewController alloc]
initWithNibName: @"ManagedObjectAttributeEditViewController" bundle: nil];
evc.editedObject = self.detailItem;
evc.delegate = self;
// Figure out from the row which attribute was selected
NSEntityDescription *entity = self.detailItem.entity;
NSDictionary *attributes = entity.attributesByName;
NSArray *keys = [attributes allKeys];
keys = [keys sortedArrayUsingSelector: @selector(compare:)];
NSString *key = [keys objectAtIndex: indexPath.row];
evc.editedFieldKey = key;
[self.navigationController pushViewController: evc animated: YES];
// The other sections are the relationships for the 'detailItem' object
} else {
// Code omitted as not relevant for the error.
}
}

ManagedObjectAttributeEditViewController 具有文本字段等,以允许编辑属性值。当它的保存按钮被触摸时执行:

- (IBAction) save {
id valueFromView;
NSAttributeType type = [self typeForEditedAttribute];
switch( type ) {
case NSDateAttributeType:
valueFromView = self.datePicker.date;
break;
case NSStringAttributeType:
if( [self.fieldKeyTester shouldUseTextViewForKey: self.editedFieldKey inEntity: self.editedObject.entity.name] ) {
valueFromView = self.textView.text;
} else {
valueFromView = self.textField.text;
}
break;
case NSInteger16AttributeType:
case NSInteger32AttributeType:
case NSInteger64AttributeType:
valueFromView = [NSNumber numberWithInteger: [self.textField.text integerValue]];
break;
case NSDecimalAttributeType:
case NSDoubleAttributeType:
case NSFloatAttributeType:
valueFromView = [NSNumber numberWithDouble: [self.textField.text doubleValue]];
break;
case NSBooleanAttributeType:
valueFromView = [NSNumber numberWithBool: self.switchControl.isOn];
break;
case NSObjectIDAttributeType:
case NSTransformableAttributeType:
case NSBinaryDataAttributeType:
case NSUndefinedAttributeType:
NSLog( @"Don't know how to handle attribute type: %d in %s", type, __func__ );
break;
default:
NSLog( @"Unrecognized attribute type: %d in %s", type, __func__ );
break;
}
[self.delegate managedObjectAttributeEditViewController: self
didSaveValue: valueFromView forKey: self.editedFieldKey];
}

ManagedObjectDetailTableViewController 设置为委托(delegate),didSaveValue:forKey: 方法是:

- (void) managedObjectAttributeEditViewController: (ManagedObjectAttributeEditViewController *) controller didSaveValue: (id) value forKey: (NSString *) key {
if( value && key ) {
[self.detailItem setValue: value forKey: key];
NSError *error;
if( ![self.detailItem.managedObjectContext save: &error] ) {
// Update to handle the error appropriately.
NSLog( @"Unresolved error doing save of attribute %@.\n%@", key, error.localizedDescription );
} else {
NSLog( @"-- successfully saved" );
}
} else {
NSLog( @"Got a cancel from edit attribute" );
}
// OK, the attribute editing view controller has told us it is done, pop it
[self.navigationController popViewControllerAnimated: YES];
}

因此,如果我从实体的对象列表开始,并且它们已正确排序。我触摸一行,它推送到 ManagedObjectDetailTableViewController。我触摸其中的一个属性行,它推送到 ManagedObjectAttributeEditViewController。我更改值并触摸保存。这将弹出到 ManagedObjectDetailTableViewController,其中一切看起来都很好。然后我触摸后退按钮返回到实体的对象列表,但现在它们不再排序(它们似乎总是以相同的顺序排列,但我无法识别顺序的模式)。

如果我在执行保存 之后和触摸后退按钮之前数到 10,则列表已正确排序。

如果我在 didSaveValue:forKey: 中注释掉 [self.detailItem.managedObjectContext save: &error] 方法调用,那么实体的对象列表将保持正确排序但是如果我在自动保存发生之前退出应用程序,我将丢失更改。

这让我觉得它与 [self.detailItem.managedObjectContext save: &error] 由于某种原因未完成和获取的结果 Controller (使用相同的 NSManagedObjectContext)有关无法检索排序的数据。

我修改值的属性不涉及排序描述符,所以修改值前后显示的顺序应该是一样的。我的数据库很大,可能需要几秒钟才能将其写入磁盘。我在模拟器和设备上看到了 iOS 5.1 的问题。

有没有人经历过这样的事情或者有什么建议?

抱歉,对于美国所有的 Stackoverflowers,7 月 4 日是如此冗长和快乐!


修改后的ManagedObjectDetailTableViewController委托(delegate)方法didSaveValue:forKey:方法为:

- (void) managedObjectAttributeEditViewController: (ManagedObjectAttributeEditViewController *) controller
didSaveValue: (id) value forKey: (NSString *) key {
if( value && key ) {
[self.detailItem setValue: value forKey: key];
NSError *error;
if( ![self.detailItem.managedObjectContext save: &error] ) {
// Update to handle the error appropriately.
NSLog( @"Unresolved error doing save of attribute %@.\n%@", key, error.localizedDescription );
} else {
NSLog( @"-- successfully saved" );
if( [self.detailItem.managedObjectContext.parentContext.hasChanges] ) {
if( ![self.detailItem.managedObjectContext.parentContext save: &error] ) {
NSLog( @"Unresolved error doing save of parent context for attribute %@.\n%@", key, error.localizedDescription );
} else {
NSLog( @"-- successfully saved the parent context too!" );
}
}
}
} else {
NSLog( @"Got a cancel from edit attribute" );
}
// OK, the attribute editing view controller has told us it is done, pop it
[self.navigationController popViewControllerAnimated: YES];
}

我现在明白,为了使更改在最新的 iOS 中成为永久存储,这种双重保存是必要的,因为在父上下文中,保存只会上升一个级别。我不明白为什么不将保存传播到永久存储应该打乱排序顺序。也许我的代码中某处存在其他一些错误,这是在屏蔽,或者这只是它的工作方式......

最佳答案

好的,基于您的编辑,其中包括新的堆栈跟踪:

您正在使用 UIManagedDocument 来管理您的核心数据堆栈。这意味着第一次保存可能来自 UIDocument 的主线程上下文,第二次保存来自其后台上下文。您能否确认您正在使用 UIManagedDocument 的 managedObjectContext 上下文中的对象(而不是您自己创建的其他上下文)?

还有一点。您能否确认 entitySortDescriptorList 不会以某种方式在您的 setupFetchedResultsController 方法中变为 nil?

最后,与其他诊断一样:

  • 尝试从顶层 View Controller 调用 save:,看看会发生什么。
  • 如果你为你的 NSFetchedResultsController 创建一个委托(delegate)会发生什么?你会收到更改通知吗?他们看起来合理吗?

关于objective-c - 保存列出的对象之一后 NSFetchedResultsController 损坏排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11334907/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com