OC中跨控制器传递NSManagedObject偶现Fault对象,求可行传递方式
解决跨控制器传递NSManagedObject时出现Fault对象的问题
NSManagedObject变成Fault对象,本质是因为它依赖的NSManagedObjectContext生命周期异常(比如原上下文被释放),或者对象被上下文标记为可回收,导致后续访问时无法触发数据加载。以下是几种可靠的跨控制器传递方案:
方案1:传递对象的Object ID,目标控制器重新获取
这是最稳妥的方式,Object ID是Core Data对象的持久化唯一标识,不受原上下文生命周期影响。
源控制器代码
OptiiMobileTaskDetailViewController *taskDetailVC = (OptiiMobileTaskDetailViewController *)segue.destinationViewController; taskDetailVC.taskObjectID = task.objectID;
目标控制器代码
@property (nonatomic, strong) NSManagedObjectID *taskObjectID; @property (nonatomic, strong) Task *task; - (void)viewDidLoad { [super viewDidLoad]; if (self.taskObjectID) { // 替换为你的上下文获取逻辑(比如共享上下文、当前控制器的私有上下文) NSManagedObjectContext *context = [self getCurrentManagedObjectContext]; self.task = (Task *)[context objectWithID:self.taskObjectID]; // 可选:提前触发属性加载,避免后续操作时出现Fault [self.task willAccessValueForKey:nil]; } }
方案2:传递属性字典(适合只读场景)
如果只需要展示对象数据,不需要修改后回存Core Data,可以手动提取所需属性封装成字典传递,完全脱离上下文依赖。
源控制器代码
OptiiMobileTaskDetailViewController *taskDetailVC = (OptiiMobileTaskDetailViewController *)segue.destinationViewController; taskDetailVC.taskInfo = @{ @"taskID": task.taskID ?: @"", @"title": task.title ?: @"", @"dueDate": task.dueDate ?: [NSDate date] };
目标控制器代码
@property (nonatomic, strong) NSDictionary *taskInfo; - (void)viewDidLoad { [super viewDidLoad]; // 直接从字典读取属性,无Core Data依赖 NSString *taskTitle = self.taskInfo[@"title"]; NSDate *dueDate = self.taskInfo[@"dueDate"]; // ... 业务逻辑处理 }
方案3:统一上下文或迁移对象到目标上下文
如果两个控制器必须直接传递对象,要确保对象的上下文与目标控制器的上下文一致,否则迁移对象到当前上下文:
目标控制器修改setTask方法
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; -(void) setTask:(Task *)task { if (task.managedObjectContext != self.managedObjectContext) { // 上下文不一致时,从当前上下文重新获取对象 _task = [self.managedObjectContext objectWithID:task.objectID]; } else { _task = task; } }
额外注意事项
- 禁止跨线程传递NSManagedObject:后台线程上下文创建的对象,不能直接传递到主线程控制器使用,必须通过Object ID在主线程上下文重新获取。
- 避免原控制器提前释放:如果源控制器被销毁,其持有的上下文可能被释放,导致传递的对象变成无效Fault。
内容的提问来源于stack exchange,提问作者Jatin Dave
相关产品推荐
相关产品推荐

