RestKit:'NSInternalInconsistencyException',原因:'无法执行映射:没有分配`managedObjectContext`

Posted

技术标签:

【中文标题】RestKit:\'NSInternalInconsistencyException\',原因:\'无法执行映射:没有分配`managedObjectContext`【英文标题】:RestKit: 'NSInternalInconsistencyException', reason: 'Unable to perform mapping: No `managedObjectContext` assignedRestKit:'NSInternalInconsistencyException',原因:'无法执行映射:没有分配`managedObjectContext` 【发布时间】:2014-12-08 02:57:17 【问题描述】:

我收到以下错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to perform mapping: No `managedObjectContext` assigned. (Mapping response.URL = https://www.someurl.com/lastrequest=2014-12-08T02%3A44%3A52Z)'

应用程序在 RKResponseMapperOperation.m 中的以下行停止:

- (RKMappingResult *)performMappingWithObject:(id)sourceObject error:(NSError **)error


    NSLog(@"managedObjectContext: %@,    Source Object: %@        Error: %@", self.managedObjectContext, sourceObject, (*error).description);
    NSAssert(self.managedObjectContext, @"Unable to perform mapping: No `managedObjectContext` assigned. (Mapping response.URL = %@)", self.response.URL);
....

我注意到在应用程序崩溃之前,上述方法被调用了 27 次(这个数字不同)。在每个实例中,都存在 NSManagedObjectContext,即下面的行:

2014-12-07 18:44:48.721 MyApp[19011:3258405] managedObjectContext:managedObjectContext: <NSManagedObjectContext: 0x1701f5800>,    Source Object: 
    friends =     (
    );
        Error: (null)

然而就在它崩溃之前,NSManagedObjectContext 为空:

2014-12-07 18:44:53.454 MyApp[19011:3258404] managedObjectContext: (null),    Source Object: 
    friends =     (
    );
        Error: (null)

由于应用程序在崩溃之前可以正常运行一段时间,我不知道如何解决这个问题。任何指针将不胜感激。

* 编辑 *

在 Appdelegate 中。该方法在用户登录时在 viewDidLoad 中调用一次。

- (RKManagedObjectStore *)managedObjectStore

    if (!_managedObjectStore && [Persistence loggedIn])
    
        NSError * error;
        NSURL * modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"App" ofType:@"momd"]];
        NSManagedObjectModel * managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
        self.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];

        [_managedObjectStore createPersistentStoreCoordinator];

        NSArray * searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString * documentPath = [searchPaths objectAtIndex:0];

        NSString *dbName = [NSString stringWithFormat:@"%@App%@.sqlite", documentPath, [Persistence username]];
        NSPersistentStore * persistentStore = [_managedObjectStore addSQLitePersistentStoreAtPath:dbName
                                                                           fromSeedDatabaseAtPath:nil
                                                                                withConfiguration:nil
                                                                                          options:[self optionsForSqliteStore]
                                                                                            error:&error];
        NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);

        NSLog(@"Path: %@", dbName);

        if(!persistentStore)
        
            NSLog(@"Failed to add persistent store: %@", error);
        

        [_managedObjectStore createManagedObjectContexts];
        self.managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:self.managedObjectStore.persistentStoreManagedObjectContext];

        return self.managedObjectStore;
    

    return _managedObjectStore;


- (id)optionsForSqliteStore

    return @
             NSInferMappingModelAutomaticallyOption: @YES,
             NSMigratePersistentStoresAutomaticallyOption: @YES
             ;

创建 MOC: 对于 Core Data 堆栈,我使用的是在 Xcode 中创建项目时提供的 AppDelegate 中的 Default Core Data 代码。

- (NSManagedObjectContext *)managedObjectContext

    if (_managedObjectContext != nil) 
        return _managedObjectContext;
    

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) 
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return _managedObjectContext;

MOC操作:

- (void)saveContext

    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) 
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) 
             // Replace this implementation with code to handle the error appropriately.
             // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
         
    

在App内部,以下方法用于设置、获取和清除ObjectManager:

- (void)refreshMOC

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    self.objectManager = [self getObjectManager];

    self.objectManager.managedObjectStore = appDelegate.managedObjectStore;
    self.objectManager.managedObjectStore.managedObjectCache = appDelegate.managedObjectStore.managedObjectCache;
    self.managedObjectContext = self.objectManager.managedObjectStore.mainQueueManagedObjectContext;


- (RKObjectManager *)setupObjectManager

    NSURL *baseURL = [NSURL URLWithString:kBaseURL];
    AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:baseURL];
    RKObjectManager *manager = [[RKObjectManager alloc]initWithHTTPClient:httpClient];
    [manager.HTTPClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
    [manager.HTTPClient setParameterEncoding:AFJSONParameterEncoding];
    [RKMIMETypeSerialization registeredMIMETypes];
    [RKObjectManager setSharedManager:manager];

    return [RKObjectManager sharedManager];


- (RKObjectManager *)getObjectManager

    self.objectManager = (!self.objectManager) ?  [self setupObjectManager] : self.objectManager;
    return self.objectManager;


- (RKObjectManager*)newObjectManager

    [self clearRKObjectManager];
    return [self getObjectManager];


- (void)clearRKObjectManager

    if (self.objectManager)
    
        self.objectManager = nil;
    

【问题讨论】:

您在哪里设置了核心数据堆栈并创建了 MOC?显示代码。 谢谢。请参阅上面的编辑。 @Wain -- 有什么想法吗? 【参考方案1】:

删除所有应用程序委托模板 Core Data 方法。当您使用 RestKit 并创建托管对象存储时,您要求 RestKit 为您管理核心数据堆栈,因此不需要那些其他方法(并且会混淆事情)。

当您需要 MOC 时,从托管对象存储中获取它/一个。

注意,以上内容也适用于保存,因为您需要使用 RestKit 方法保存到持久存储,而不是仅保存单个 MOC。

【讨论】:

我确实删除了所有模板代码,但错误仍然存​​在。我唯一能想到的就是多线程。有时我可以同​​时获取五个并发调度队列。你认为这可能是问题吗?如果是这样,有关如何使用 RESTKit 处理多线程的任何建议? 你在用这些线程做什么?只是触发 RestKit?怎么样? 如果您在没有调用 refreshMoc 的情况下调用 setupObjectManager,您的代码中确实可能存在漏洞 我在后台线程中获取。即对于 viewWillAppear 中的 tabBar 中的每个选项卡,我都会进行一次获取(GET)。如果用户在选项卡之间切换得非常快,应用程序就会崩溃。我将通过代码验证我没有在refreshMoc 之前调用setupObjectManager 我刚刚验证,在refreshMOC 之前我调用setupObjectManager 的代码中没有位置。您认为值得花时间尝试处理具有多个 MOCs 的线程吗?

以上是关于RestKit:'NSInternalInconsistencyException',原因:'无法执行映射:没有分配`managedObjectContext`的主要内容,如果未能解决你的问题,请参考以下文章

RestKit 0.20:restkit 对象映射使属性映射加倍

将“import <RestKit/RestKit.h>”添加到 AppDelegate.m 的问题

RestKit 与直接 CoreData

Restkit 0.20.x cocoapods 安装问题 - 编译但找不到 RestKit 的导入

RestKit / Core Data / Offline - 我需要 UUID 还是 RestKit 足够聪明?

RestKit 核心数据集成