【问题标题】:NSManagedObjectContext doesn't refresh correctlyNSManagedObjectContext 没有正确刷新
【发布时间】:2011-10-22 12:24:51
【问题描述】:

嗨 :) 我也有类似的问题,例如Working with the same NSManagedObjectContext in multiple tabs
背景:
我的 managedObjectContext(进一步的 MOC)在我的 appDelegate 类中初始化,并通过
myViewController.managedObjectContext = self.managedObjectContext; 或在带有 self.managedObjectContext = pContext; 的 init 方法中传递到多个选项卡 流程是:第一个视图是一个简单的集合列表。使用 NSFetchedResultsController (myViewController : UITableViewController<NSFetchedResultsControllerDelegate>) 获取集合。通过选择一个,您可以更深入地导航,但仍会通过此 MOC。
在下一个控制器(detailsViewController)中,我列出了这个集合中我可以与之交互的一些项目(例如设置开关)。
我还有一个editingObjectContext:

// DetailsViewController.m
NSManagedObjectContext* editingContext = [[NSManagedObjectContext alloc] init];
[editingContext setPersistentStoreCoordinator:[managedObjectContext persistentStoreCoordinator]];
self.editingObjectContext = editingContext;

现在我的问题:因为我的视图必须旋转,所以我使用以下技巧:

// DetailsViewController.m
DetailsView *localAct = [[DetailsView alloc] initWithManagedObjectContext:managedObjectContext ... ]
DetailsView *localSen = [[DetailsView alloc] initWithManagedObjectContext:managedObjectContext ... ]

UITableView *localContainerView = [[UITableView alloc] init];
self.containerView = localContainerView;
[localContainerView release];
//[...]
[containerView addSubview:actuatorView];
self.tableView = containerView;

此外,我还有一个按钮来管理这些项目(应显示哪些项目,哪些不显示)。这个按钮只是用一个新的 fetchResult 重新加载表。

// DetailsView.m
- (void) manageItems{
managing = !managing;
[viewController setIsManaging:managing]; // parent
self.fetchedResultsController = nil;

NSError *error = nil;
[[self fetchedResultsController] performFetch:&error];

[self reloadData];
[self updateBarButton];
}

将项目放入上下文的方法如下所示:

// DetailsViewController.m
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// init + create predicate
NSSet* set = [sen filteredSetUsingPredicate:predicate];
if( [set count] > 0 )
{
    for( Act* act in set )
    {
        [editingObjectContext deleteObject:act];
    }
}
else
{
    Act* act = [NSEntityDescription insertNewObjectForEntityForName:@"Act" inManagedObjectContext:editingObjectContext];

    // do things
}
NSError *error = nil;
[[detailView fetchedResultsController] performFetch:&error];

[self.containerView reloadData];
[detailView reloadData];
}

但是在我在托管视图中选择项目并单击保存 (manageItems) 后,视图不会显示它们:/ 我必须切换选项卡或在其他控制器(父级或更深)中导航以实现它. 我的 ViewWillAppear 方法:

// DetailsViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
DetailsView *detailView = se ? senView : actView;
// [do uninteresting stuff]
[detailView.fetchedResultsController performFetch:nil];
[self.tableView reloadData];
// [do uninteresting stuff]
}

和 viewWillDisapper 调用

- (void)saveChanges
{
if( ![editingObjectContext hasChanges] )
    return;

// send save-command to server
}

在一个较早的 Verison 中,它只有 1 个视图,但我并没有太大变化……:/ 所以我不明白 MOC 为什么会这样。 “manageItems”部分几乎相等,只是在新版本中更深一层(在 DetailsView 而不是控制器中)...

如果有人能告诉我我可以尝试什么(在管理和正常之间切换时始终保存到服务器不是解决方案,因为服务器响应的延迟对于刷新来说太高了,所以我有更少的翻转视图。同样使用 self.tableView / detailView / self.containerView refresh 刷新视图会带来相同的结果:/)。

第二个问题:发送到服务器后我无法调用“editingObjectContext save:”方法,因为它会抛出错误并且根本不保存到本地数据库。

handleChangeResponse 中的错误: 错误域=NSCocoaErrorDomain 代码=133020“操作无法完成。(Cocoa 错误 133020。)”UserInfo=0x4d8bb90 {conflictList=( “NSManagedObject (0x5a46a80) 的 NSMergeConflict (0x5a2fac0),objectID 为‘0x5a46420’,oldVersion = 7 和 newVersion = 8,旧对象快照 = {\n iconName = noicon;\n [...];\n} 和新的缓存行= {\n iconName = noicon;\n [...] \n}" )}

如果您有疑问或需要更多代码(即旧版本),请询问;)

感谢期待:)

【问题讨论】:

  • 好的,我找到了一个可以使用翻转视图的版本...已经将代码复制到新版本中,但仍然是同样的问题...:/ - (void)manageItems /* DetailsViewController */ { DetailsView *detailView = isSen? senView : actView; [detailView manageItems]; } --- - (void)manageItems //DetailsView { managing = !managing; [viewController setIsManaging:managing]; /* parent */ self.fetchedResultsController = nil; NSError *error = nil; [[self fetchedResultsController] performFetch:&error]; [viewController.containerView reloadData]; [self updateBarButton]; }

标签: iphone objective-c merge conflict nsmanagedobjectcontext


【解决方案1】:

看来我有办法了!从 IOS 5.0 开始,NSManagedObjectContext 有了一个新方法:

[managedObjectContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];

发现于http://pauloliveira.net/tech/core-data-merging-conflicts
将此属性设置为顶级 MOC(在我的情况下是在 appDelegate 中),别无其他!清除了我的合并问题;)

【讨论】:

  • setMergePolicy: 适用于 iOS 3.0
【解决方案2】:

这可能是由于管理对象上下文在使用你得到这个的对象时。在您注销或返回时删除所有 NSManagebobject。说结束使用应用程序。好像是这样的……

[NSManagebobjectcontext setManagedObjectsDictionary:[NSMutableDictionary dictionary]];

【讨论】:

    【解决方案3】:

    我找到了它不起作用的原因...忘记我上面写的所有内容...问题出在 fetchrequest 中 - 具体来说:在谓词中...在我使用的早期版本中

    [NSComparisonPredicate predicateWithLeftExpression: ...] 
    

    在我使用的实际版本中

    NSString * predicateFormat = [NSString stringWithFormat: ...];
    NSPredicate* predicate = [NSPredicate predicateWithFormat:predicateFormat];
    

    因为我不得不扩展选项的数量并且还编辑了请求本身,因为它在谓词中产生了问题(比较一个完整的对象(MOC 类,从数据库中提取)与一个实体不起作用,所以我在 DetailsViewController 中管理了解决方法,并且没有在这个地方回滚我的更新:/)。
    从来没想过要在这个问题上浪费这么多时间>。

    我会检查第二个问题(保存问题)是否仍然存在。如果没有,我会更新我的帖子,否则这个话题没有关闭:/

    【讨论】:

      猜你喜欢
      • 2018-06-04
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      • 1970-01-01
      相关资源
      最近更新 更多