用于不同视图控制器中不同Web服务的RestKit映射 [英] RestKit Mapping for different web services in different view controllers

查看:93
本文介绍了用于不同视图控制器中不同Web服务的RestKit映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am developing an iPad App. I have three different view controllers wherein I call three different web services using RestKit and map them to core data entity. I display the data in all view controllers by using NSFetchedResultsController.

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

First time when I try to load the data, it works correctly on all the view controllers. Later when I come up to the first view controller and try to load the data, it fails. I feel I am messing something.

这是我的代码。在AppDelegate中,我初始化RestKit:

Here is my code. In AppDelegate, I initialize 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;

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

In the first view controller, I setup mapping and other required things as shown below:

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

这是获取的结果控制器代码:

and here is the fetchedresultscontroller code:

- (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服务并映射到不同的核心数据实体:

In other view controller, I am calling different web service and mapping to different core data entity:

这是其他视图控制器中的代码:

Here is the code in other view controller:

 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代码:

FetchedResultsController code:

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

我确定问题所在?

推荐答案

问题是您所有的响应描述符路径模式均为nil。这意味着所有响应描述符都将应用于所有响应。 RestKit会创建一个被告知要匹配的描述符的实体的实例,无论描述符中有多少键都可以映射。因此,您将创建大量填充了错误类型的部分填充实例。

The problem is that all of your response descriptors path patterns are nil. This means that all of the response descriptors will be applied to all responses. RestKit will create instances of whichever entity it's told to for a matching descriptor, it doesn't matter how many of the keys in the descriptor are found to map. So, you'll get a lot of partially populated instances of the wrong type created.

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

To fix, set the path pattern of each response descriptor to match the request URL path.

这篇关于用于不同视图控制器中不同Web服务的RestKit映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆