不同视图控制器中不同 Web 服务的 RestKit 映射

RestKit Mapping for different web services in different view controllers

我正在开发 iPad 应用程序。我有三个不同的视图控制器,其中我使用 RestKit 调用三个不同的 Web 服务并将它们映射到核心数据实体。我使用 NSFetchedResultsController 在所有视图控制器中显示数据。

我第一次尝试加载数据时,它在所有视图控制器上都能正常工作。后来当我来到第一个视图控制器并尝试加载数据时,它失败了。我觉得我在搞砸什么。

这是我的代码。在 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;

在第一个视图控制器中,我设置了映射和其他所需的东西,如下所示:

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");
}
];

FetchedResultsController 代码:

- (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;
}

你能帮我找出问题所在吗?

问题是您所有的响应描述符路径模式都是零。这意味着所有响应描述符都将应用于所有响应。 RestKit 将创建它被告知要为匹配的描述符创建的任何实体的实例,而不管描述符中有多少键被发现要映射。因此,您会得到很多创建错误类型的部分填充实例。

要修复,请设置每个响应描述符的路径模式以匹配请求 URL 路径。