2015-11-06 53 views
0

我有iPad應用程序與三個視圖控制器在uitabbarcontroller。在每個視圖控制器中,我調用不同的Web服務並使用RestKit將它們映射到核心數據實體,然後使用nsfetchedresultscontroller在uitableview中顯示數據。有關我的實施的更多信息是hereRestKit - '不能添加對象與實體'entityName'緩存'entityName'的實體'

第一次加載數據時,數據在每個視圖控制器上正確加載和映射,但是在視圖控制器中的一個視圖控制器中,當我嘗試在視圖控制器-3中加載數據後重新加載視圖控制器-2中的數據時,應用程序崩潰與以下錯誤:

2015-11-07 00:17:45.205 PharmacyStockTake [193:3854] T restkit.network:RKResponseMapperOperation.m:504映射HTTP響應到零目標對象... 2015-11-07 00:17:45.206 PharmacyStockTake [193:3854]我restkit.core_data:RKInMemoryManagedObjectCache.m:94實體的'RackStockTakeStatus'的屬性'stockTakeLocId'的緩存實例 2015-11-07 00:17:45.213 PharmacyStockTake [193:3854] *斷言失敗 - [RKEntityByAttributeCache addObjects:completion:],/Users/saif/Documents/iDev/ComPrjs/PharmacyStockTake/Pods/RestKit/Code/CoreData/RKEntityByAttributeCache.m:333 2015-11-07 00:17: 45.214 PharmacyStockTake [193:3854] *因未捕獲的異常'NSInternalInconsistencyException'而終止應用程序,原因:'無法將實體'RackStockTakeStatus'的對象添加到'RackStockTakeStatus'實體的緩存中' ***第一次投擲調用堆棧: 0x2201585b 0x33a5adff 0x22015731 0x22da6ddb 0x14b67b 0x21d9034b 0x21d9022d 0x14b175 0x15a9e1 0x21d9034b 0x21d9022d 0x15a71d 0x161327 0x17bfb9 0x17a769 0x220091e9 0x21f8bbdb 0x17a65b 0x17c21b 0x17c9cd 0x17d271 0x22d283cf 0x1c3925 0x21d9034b 0x422d03 0x42c4fb 0x21d90247 0x1c26bb 0x1c072d 0x22d283cf 0x22dd682d 0x42d61b 0x425f53 0x42eb0f 0x42e961 0x34314e0d 0x343149fc) 的libC++ ABI。dylib:與類型NSException

這裏捕獲的異常終止是我的代碼:在AppDelegate中

初始化RestKit:

RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL]; 
 
    
 
    //[RKObjectManager setSharedManager:objectManager]; 
 
    [RKObjectManager setSharedManager:objectManager]; 
 
    
 
    
 
    // Initialize managed object model from bundle 
 
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; 
 
    
 
    // Initialize managed object store 
 
    RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; 
 
    objectManager.managedObjectStore = managedObjectStore; 
 
    
 
    // Complete Core Data stack initialization 
 
    [managedObjectStore createPersistentStoreCoordinator]; 
 
    NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"StockTakeDB.sqlite"]; 
 
    NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"StoreItemsDB" ofType:@"sqlite"]; 
 
    NSError *error; 
 
    NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error]; 
 
    NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error); 
 
    
 
    // Create the managed object contexts 
 
    [managedObjectStore createManagedObjectContexts]; 
 
    
 
    // Configure a managed object cache to ensure we do not create duplicate objects 
 
    managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];

RestKit初始化和配置代碼視圖 - 控制器 - 2:

-(void)initTakeStockRestKit 
 
{ 
 
    takeStockLocationWithStatusRequestPath = @"/stocktake/stocktake/1/usr/1/locwithstatus"; 
 
    RKObjectManager *objectManager = [RKObjectManager sharedManager]; 
 
    
 
    [[NSURLCache sharedURLCache] removeAllCachedResponses]; 
 

 
    // Initialize managed object model from bundle 
 
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; 
 
    
 
    // Initialize managed object store 
 
    RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; 
 
    objectManager.managedObjectStore = managedObjectStore; 
 
    
 
    // Complete Core Data stack initialization 
 
    [managedObjectStore createPersistentStoreCoordinator]; 
 
    NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"StockTakeDB.sqlite"]; 
 
    NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"StoreItemsDB" ofType:@"sqlite"]; 
 
    NSError *error; 
 
    NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error]; 
 
    NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error); 
 
    
 
    // Create the managed object contexts 
 
    [managedObjectStore createManagedObjectContexts]; 
 
    
 
    // Configure a managed object cache to ensure we do not create duplicate objects 
 
    managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; 
 
    
 
    [objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) { 
 
     RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:takeStockLocationWithStatusRequestPath]; 
 
     
 
     NSDictionary *argsDict = nil; 
 
     BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict]; 
 
     
 
     if (match) { 
 
      NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"RackStockTakeStatus"]; 
 
      return fetchRequest; 
 
     } 
 
     return nil; 
 
    }]; 
 

 
    RKEntityMapping *rackStockTakeStatusListMapping = [RKEntityMapping mappingForEntityForName:@"RackStockTakeStatus" inManagedObjectStore:managedObjectStore]; 
 
    rackStockTakeStatusListMapping.identificationAttributes = @[@"stockTakeLocId"]; 
 
    
 
    [rackStockTakeStatusListMapping addAttributeMappingsFromDictionary: 
 
    @{ 
 
     @"stockTakeLocId" : @"stockTakeLocId", 
 
     @"stockTakeUuid" : @"stockTakeUuid", 
 
     @"locId" : @"locId", 
 
     @"locName" : @"locName", 
 
     @"status" : @"status", 
 
     @"stockTakeByUser" : @"stockTakeByUser", 
 
     @"stockTakeByUserId" : @"stockTakeByUserId", 
 
     @"beginTime" : @"beginTime", 
 
     @"percentCompleted" : @"percentCompleted" 
 
     } 
 
    ]; 
 
    
 
    RKResponseDescriptor *rackStockTakeStatusListResponseDescriptor = 
 
    [RKResponseDescriptor responseDescriptorWithMapping:rackStockTakeStatusListMapping 
 
               method:RKRequestMethodGET 
 
              pathPattern:@"/stocktake/stocktake/:id/usr/:id/locwithstatus" 
 
               keyPath:nil 
 
              statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful) 
 
    ]; 
 
    
 
    [objectManager addResponseDescriptor:rackStockTakeStatusListResponseDescriptor]; 
 
}

數據加載視圖 - 控制器-2:

NSString *requestPath = [NSString stringWithFormat:@"/stocktake/stocktake/%@/usr/1/locwithstatus",[defaults objectForKey:@"loggedInUserSelectedStoreId"]]; 
 

 
[[RKObjectManager sharedManager] 
 
    getObjectsAtPath:requestPath 
 
    parameters:nil 
 
    success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 
 
      NSManagedObjectContext *context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext; 
 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"RackStockTakeStatus" inManagedObjectContext:context]; 
 
    [request setEntity:entity]; 
 
    NSError *error; 
 
    [context executeFetchRequest:request error:&error]; 
 
      NSError *error; 
 
    if (![[self fetchedResultsController] performFetch:&error]) { 
 
    } 
 
     [self.tableView reloadData]; 
 
     NSLog(@"requestDataItemsForStore - Mapping Success"); 
 
    } 
 
    failure: ^(RKObjectRequestOperation *operation, NSError *error) { 
 
     RKLogError(@"Load failed with error: %@", error); 
 
     NSLog(@"requestDataItemsForStore - Loading Failed"); 
 
    } 
 
    ];

RestKit初始化和在視圖 - 控制器-3配置代碼:

RKObjectManager *objectManager = [RKObjectManager sharedManager]; 
 
    
 
    // Initialize managed object model from bundle 
 
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; 
 
    
 
    // Initialize managed object store 
 
    RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; 
 
    objectManager.managedObjectStore = managedObjectStore; 
 
    
 
    // Complete Core Data stack initialization 
 
    [managedObjectStore createPersistentStoreCoordinator]; 
 
    NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"StockTakeDB.sqlite"]; 
 
    NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"StoreItemsDB" ofType:@"sqlite"]; 
 
    NSError *error; 
 
    NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error]; 
 
    NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error); 
 
    
 
    // Create the managed object contexts 
 
    [managedObjectStore createManagedObjectContexts]; 
 
    
 
    // Configure a managed object cache to ensure we do not create duplicate objects 
 
    managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; 
 
    
 
    [objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) { 
 
     RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:itemsByLocationRequestPath]; 
 
     
 
     NSDictionary *argsDict = nil; 
 
     BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict]; 
 
     
 
     if (match) { 
 
      NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ItemsByLocation"]; 
 
      return fetchRequest; 
 
     } 
 
     
 
     return nil; 
 
    }]; 
 
    
 
     RKEntityMapping *itemsByLocationListMapping = [RKEntityMapping mappingForEntityForName:@"ItemsByLocation" inManagedObjectStore:managedObjectStore]; 
 
     itemsByLocationListMapping.identificationAttributes = @[@"itemId"]; 
 
    
 
     [itemsByLocationListMapping addAttributeMappingsFromDictionary: 
 
     @{ 
 
      @"itemId" : @"itemId", 
 
      @"itemName" : @"itemName", 
 
      @"itemCode" : @"itemCode", 
 
      @"uomCode" : @"uomCode", 
 
      @"locId" : @"locId", 
 
      @"locName" : @"locName", 
 
      @"subLocId" : @"subLocId", 
 
      @"subLocName" : @"subLocName", 
 
      @"storeItemId" : @"storeItemId", 
 
      @"stockTakeQtyId" : @"stockTakeQtyId", 
 
      @"countedTime" : @"countedTime", 
 
      @"countQty" : @"countQty", 
 
      @"removed" : @"removed", 
 
      @"remarks" : @"remarks" 
 
      } 
 
     ]; 
 
    
 
     RKResponseDescriptor *itemsByLocationListResponseDescriptor = 
 
     [RKResponseDescriptor responseDescriptorWithMapping:itemsByLocationListMapping 
 
                method:RKRequestMethodGET 
 
               pathPattern:@"/stocktake/stocktake/:id/loc/:id/usr/:id/items" 
 
                keyPath:nil 
 
               statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful) 
 
     ]; 
 
    
 
     [objectManager addResponseDescriptor:itemsByLocationListResponseDescriptor];
在視圖控制器-

數據加載:

[[RKObjectManager sharedManager] 
 
    getObjectsAtPath:itemsByLocationRequestPath 
 
    parameters:nil 
 
    success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 
 
     NSManagedObjectContext *context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext; 
 
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ItemsByLocation"]; 
 
    
 
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"subLocName" ascending:YES]; 
 
    fetchRequest.sortDescriptors = @[descriptor]; 
 
    
 
    NSError *error = nil; 
 
    [context executeFetchRequest:fetchRequest error:&error]; 
 
      NSError *error; 
 
    if (![[self fetchedResultsController] performFetch:&error]) { 
 

 
    } 
 
     [self.tableView reloadData]; 
 
     NSLog(@"requestDataItemsForStore - Mapping Success"); 
 
    } 
 
    failure: ^(RKObjectRequestOperation *operation, NSError *error) { 
 
     RKLogError(@"Load failed with error: %@", error); 
 
     NSLog(@"requestDataItemsForStore - Loading Failed"); 
 
    } 
 
    ];

你能幫助解決這個問題?

+0

@很抱歉,您需要幫助。提前致謝。 – saif

回答

1

這是一個線程和/或多上下文問題。你的實體緩存設置有一個上下文,但是你從另一個上下文中使用它(這就是爲什麼實體具有相同名稱但不同)的原因。

這可能是因爲你設置了多個不同的核心數據棧(它看起來像代碼樣本)。在這種情況下,您應該將所有核心數據堆棧分解出來,並將創建代碼映射到新的類 - 數據管理器。將數據管理器傳遞給每個視圖控制器,以便他們可以使用它來下載他們需要的內容。

如果是線程問題,那麼打開核心數據線程異常可以幫助您找到原因。

請注意,在每個視圖控制器中使用FRC是好的,但您應該只有一個主線程上下文,您將它們全部設置。

+0

感謝您的回覆。你能解釋一下如何用一個例子來實現嗎? – saif

+0

基本上只需從一個視圖控制器中取出當前代碼並將其移動到另一個類中,即可刪除原始代碼。然後將您的映射從其他視圖控制器中移出,並從這些視圖控制器中刪除所有設置和映射代碼。現在你將所有的配置代碼放在一個地方,所以它只運行一次(它應該在類實例化時運行,並且應該從應用程序代理實例化) – Wain

+0

感謝@Wain的幫助。最後,由於其糟糕的文檔,我放棄了RestKit。我在RestKit中遇到了問題。 – saif