2015-11-05 54 views
0

我正在開發iPad應用程序。我有三個不同的視圖控制器,其中我使用RestKit調用三個不同的Web服務並將它們映射到核心數據實體。我使用NSFetchedResultsController在所有視圖控制器中顯示數據。不同視圖控制器中不同Web服務的RestKit映射

第一次當我嘗試加載數據時,它在所有視圖控制器上正常工作。後來,當我走到第一個視圖控制器並嘗試加載數據時,它失敗了。我覺得我在搞東西。

這是我的代碼。在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]; 

viewStockRestKitManagedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext; 
takeStockRestKitManagedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext; 
takeStockItemsByLocationRestKitManagedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext; 

在第一視圖控制器,I設置映射和其他所需的東西,如下所示:

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:viewStockRequestPath]; 

    NSDictionary *argsDict = nil; 
    BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict]; 

    if (match) { 
     NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"StoreItems"]; 
     return fetchRequest; 
    } 

    return nil; 
}]; 

RKEntityMapping *storeItemsListMapping = [RKEntityMapping mappingForEntityForName:@"StoreItems" inManagedObjectStore: managedObjectStore]; 
storeItemsListMapping.identificationAttributes = @[@"itemId"]; 

[storeItemsListMapping addAttributeMappingsFromDictionary: 
@{ 
    @"itemId" : @"itemId", 
    @"itemName" : @"itemName", 
    @"itemCode" : @"itemCode", 
    @"uomCode" : @"uomCode", 
    @"locId" : @"locId", 
    @"locName" : @"locName", 
    @"subLocId" : @"subLocId", 
    @"subLocName" : @"subLocName", 
    @"storeItemId" : @"storeItemId" 
    } 
]; 

RKResponseDescriptor *storeItemsListResponseDescriptor = 
[RKResponseDescriptor responseDescriptorWithMapping:storeItemsListMapping 
              method:RKRequestMethodGET 
             pathPattern:nil 
              keyPath:nil 
             statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; 

[objectManager addResponseDescriptor:storeItemsListResponseDescriptor]; 

然後我正在對象:

[[RKObjectManager sharedManager] 
getObjectsAtPath:viewStockRequestPath 
parameters:nil 
success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 
    NSLog(@"requestDataItemsForStore - Mapping Success"); 
     NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"StoreItems"]; 

NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"locName" ascending:YES]; 
fetchRequest.sortDescriptors = @[descriptor]; 

NSError *error = nil; 
[[appDelegate viewStockRestKitManagedObjectContext] executeFetchRequest:fetchRequest error:&error]; 
     NSError *error; 
if (![[self fetchedResultsController] performFetch:&error]) { 
} 
    [self.tableView reloadData]; 
} 
failure: ^(RKObjectRequestOperation *operation, NSError *error) { 
    RKLogError(@"Load failed with error: %@", error); 
    NSLog(@"requestDataItemsForStore - Loading Failed"); 
} 
]; 

這裏是fetchedresultscontroller代碼:

- (NSFetchedResultsController *)fetchedResultsController { 
if (viewStockFetchedResultsController != nil) { 
    return viewStockFetchedResultsController; 
} 

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"StoreItems" inManagedObjectContext:[appDelegate viewStockRestKitManagedObjectContext]]; 
[fetchRequest setEntity:entity]; 
NSSortDescriptor *rackNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"locName" ascending:YES]; 
NSArray *sortDescriptors = @[rackNameDescriptor]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 
viewStockFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[appDelegate viewStockRestKitManagedObjectContext] sectionNameKeyPath:@"locName" cacheName:nil]; 
viewStockFetchedResultsController.delegate = self; 
return viewStockFetchedResultsController; 

}

在其他視圖控制器,我打電話不同的web服務和映射到不同的核心數據實體:

下面是在其他視圖控制器的代碼:

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:nil 
 
keyPath:nil 
 
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful) 
 
]; 
 
[objectManager addResponseDescriptor:rackStockTakeStatusListResponseDescriptor]; 
 
then getting the objects: 
 
NSString *requestPath = [NSString stringWithFormat:@"/stocktake/stocktake/%@/usr/1/locwithstatus",[defaults objectForKey:@"loggedInUserSelectedStoreId"]]; 
 
[[RKObjectManager sharedManager] 
 
getObjectsAtPath:requestPath 
 
parameters:nil 
 
success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 
 
NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"RackStockTakeStatus" inManagedObjectContext:[appDelegate takeStockRestKitManagedObjectContext]]; 
 
[request setEntity:entity]; 
 
NSError *error; 
 
[[appDelegate takeStockRestKitManagedObjectContext] executeFetchRequest:request error:&error]; 
 
NSError *error; 
 
if (![[self fetchedResultsController] performFetch:&error]) { 
 
NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
 
} 
 
[self.tableView reloadData]; 
 
NSLog(@"requestDataItemsForStore - Mapping Success"); 
 
} 
 
failure: ^(RKObjectRequestOperation *operation, NSError *error) { 
 
RKLogError(@"Load failed with error: %@", error); 
 
NSLog(@"requestDataItemsForStore - Loading Failed"); 
 
} 
 
];

FetchedResults控制器代碼:

- (NSFetchedResultsController *)fetchedResultsController { 
 
    
 
    if (fetchedResultsController != nil) { 
 
     return fetchedResultsController; 
 
    } 
 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"RackStockTakeStatus" inManagedObjectContext:[appDelegate takeStockRestKitManagedObjectContext]]; 
 
    [fetchRequest setEntity:entity]; 
 
    NSSortDescriptor *rackNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"locName" ascending:YES]; 
 
    NSArray *sortDescriptors = @[rackNameDescriptor]; 
 
[fetchRequest setSortDescriptors:sortDescriptors]; 
 
    fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[appDelegate takeStockRestKitManagedObjectContext] sectionNameKeyPath:nil cacheName:nil]; 
 
    fetchedResultsController.delegate = self; 
 
return fetchedResultsController; 
 
}

你能幫我找出問題?

+0

失敗如何?因爲你正在添加重複的映射?或者因爲你正在關閉對象存儲?集中您的設置,以免重複執行 - 即不要將其放入視圖控制器中。 – Wain

+0

@當然,當我切換視圖控制器時,它以某種方式加載其他視圖控制器所需的數據。我不確定爲什麼會發生這種情況。我不認爲我有重複的映射,請您指出重複的映射? – saif

+0

對此有幫助嗎? – saif

回答

0

問題是所有的響應描述符路徑模式都是零。這意味着所有的響應描述符都將應用於所有響應。 RestKit將創建它被告知匹配描述符的任何實體的實例,無論描述符中有多少個鍵被映射,都無關緊要。所以,你會得到很多部分填充的錯誤類型的實例。

要修復,請設置每個響應描述符的路徑模式以匹配請求URL路徑。

+0

這似乎解決了數據加載問題。現在我在一個vc中面對不同的事情。應用程序與下面的錯誤而崩潰: – saif

+0

這裏是崩潰日誌: 我restkit.core_data:RKInMemoryManagedObjectCache.m:在實體「RackStockTakeStatus」的94個緩存實例由屬性「stockTakeLocId」 ***斷言失敗 - [RKEntityByAttributeCache addObjects :完成:],StockTake/Pods/RestKit/Code/CoreData/RKEntityByAttributeCache.m:333 **由於未捕獲的異常'NSInternalInconsistencyException',原因:'無法添加對象實體'RackStockTakeStatus' RackStockTakeStatus'' – saif

+0

請開始一個新的問題,包括崩潰細節,完整的堆棧跟蹤以及該實體的映射和請求代碼 – Wain

相關問題