我使用Reskit从纽约时报畅销书JSON API获取数据。我相信我的属性映射存在问题。必须获取的典型JSON对象类似于下面的结构。我的代码也会显示出来。 API调用确实返回与预期结果数匹配的对象,但requestDataFromAPI方法中的RKMappingResult返回“[__NSCFBoolean length]:发送到实例的无法识别的选择器”。我无法访问它们,因为打印书籍没有。我不确定我做错了什么。
{
"status":"OK",
"copyright":"Copyright (c) 2016 The New York Times Company. All Rights Reserved.",
"num_results":10,
"last_modified":"2016-03-04T13:12:31-05:00",
"results":
{
"list_name":"Animals",
"bestsellers_date":"2016-02-27",
"published_date":"2016-03-13",
"display_name":"Animals",
"normal_list_ends_at":10,
"updated":"MONTHLY",
"books": [
{"rank":1,
"rank_last_week":0,
"weeks_on_list":0,
"asterisk":0,
"dagger":0,
"primary_isbn10":"0802123414",
"primary_isbn13":"9780802123411",
"publisher":"Grove Atlantic",
"description":"A grief-stricken British woman decides to raise a goshawk, a fierce bird that is notoriously difficult to tame.",
"price":0,
"title":"H IS FOR HAWK","author":"Helen Macdonald",
"contributor":"by Helen Macdonald",
"isbns": [
{"isbn10":"0802123414",
"isbn13":"9780802123411"
},
{"isbn10":"1448130727",
"isbn13":"9781448130726"
},
{"isbn10":"1481530968",
"isbn13":"9781481530965"
},
{"isbn10":"148153095X",
"isbn13":"9781481530958"
},
{"isbn10":"1410483614",
"isbn13":"9781410483614"
},
{"isbn10":"0802124739",
"isbn13":"9780802124739"
}]
}
}
- (void) initializeRestAPI
{
// Initialize RestKit using API base address
NSURL * baseURL = [NSURL URLWithString:@"http://api.nytimes.com"];
RKObjectManager * objectManager = [RKObjectManager managerWithBaseURL:baseURL];
// Initialize Core Data's managed object model from the bundle
NSManagedObjectModel * managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
// Initialize RestKit's managed object store
RKManagedObjectStore * managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;
// Complete Core Data stack initialization via RestKit
[managedObjectStore createPersistentStoreCoordinator];
NSString * persistentStorePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"DataModel.sqlite"];
NSString * seedDatabasePath = [[NSBundle mainBundle] pathForResource:@"RKSeedDatabase" ofType:@"sqlite"];
NSError * error;
NSPersistentStore * persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:persistentStorePath fromSeedDatabaseAtPath:seedDatabasePath withConfiguration:nil options:nil error:&error];
NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);
// Create RestKit's managed object contexts
[managedObjectStore createManagedObjectContexts];
// Configure a managed object cache
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
[self setupEntityMappingForObjectStore:managedObjectStore withObjectManager:objectManager];
[self requestDataFromAPI];
}
-(void) setupEntityMappingForObjectStore: (RKManagedObjectStore *) managedObjectStore withObjectManager: (RKObjectManager *) objectManager
{
RKEntityMapping * bookListMapping = [RKEntityMapping mappingForEntityForName:@"BookList" inManagedObjectStore:managedObjectStore];
bookListMapping.identificationAttributes = @[@"listName"];
[bookListMapping addAttributeMappingsFromDictionary:
@{@"results.list_name": @"listName",
@"results.bestsellers_date": @"bestsellersDate",
@"results.published_date": @"publishedDate",
@"results.display_name": @"displayName",
@"results.normal_list_ends_at": @"normalListEndsAt",
@"results.updated": @"updated"
}];
RKEntityMapping * bookMapping = [RKEntityMapping mappingForEntityForName:@"Book" inManagedObjectStore:managedObjectStore];
bookMapping.identificationAttributes = @[@"title"];
[bookMapping addAttributeMappingsFromDictionary:
@{@"rank": @"rank",
@"rank_last_week": @"rankLastWeek",
@"weeks_on_list": @"weeksOnList",
@"primary_isbn10": @"primaryIsbn10",
@"primary_isbn13": @"primaryIsbn13",
@"amazon_product_url": @"productUrl",
@"book_image": @"bookImage",
@"publisher": @"publisher",
@"description": @"bookDescription",
@"title": @"title",
@"contributor": @"contributor",
@"author": @"author",
@"price": @"price"
}];
[bookListMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"results.books" toKeyPath:@"books" withMapping:bookMapping]];
RKResponseDescriptor * bookListResponseDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:bookListMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:@"results.books"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)
];
[objectManager addResponseDescriptor:bookListResponseDescriptor];
// Enable Activity Indicator Spinner
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
}
- (void)fetchBooksFromContext
{
NSManagedObjectContext * context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSFetchRequest * fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"BookList"];
NSSortDescriptor * descriptor = [NSSortDescriptor sortDescriptorWithKey:@"listName" ascending:YES];
fetchRequest.sortDescriptors = @[descriptor];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
BookList * bookList = [fetchedObjects firstObject];
NSArray * books = [bookList.books allObjects];
//NSArray * books = [fetchedObjects firstObject];
NSLog(@"Books: %@",books);
}
- (void)requestDataFromAPI
{
NSDictionary * apiKeyData = [[NSUserDefaults standardUserDefaults] objectForKey:@"apiKeyData"];
NSString * apiKey = [apiKeyData objectForKey:@"apiKeyData"];
NSLog(@"requestDataFromAPI apiKey: %@",apiKey);
NSString * requestPath = [[NSString alloc] initWithFormat:@"/svc/books/v3/lists/%@?&api-key=%@",_categoryListName, apiKey];
[[RKObjectManager sharedManager]
getObjectsAtPath:requestPath
parameters:nil
success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
[self fetchBooksFromContext];
}
failure: ^(RKObjectRequestOperation *operation, NSError *error)
{
RKLogError(@"Loading from API failed with error: %@", error);
}
];
}
核心数据对象模型如图所示
#import "BookList.h"
NS_ASSUME_NONNULL_BEGIN
@interface BookList (CoreDataProperties)
@property (nullable, nonatomic, retain) NSString *listName;
@property (nullable, nonatomic, retain) NSDate *bestsellersDate;
@property (nullable, nonatomic, retain) NSDate *publishedDate;
@property (nullable, nonatomic, retain) NSString *displayName;
@property (nullable, nonatomic, retain) NSNumber *normalListEndsAt;
@property (nullable, nonatomic, retain) NSString *updated;
@property (nullable, nonatomic, retain) NSSet<Book *> *books;
@end
@interface BookList (CoreDataGeneratedAccessors)
- (void)addBooksObject:(Book *)value;
- (void)removeBooksObject:(Book *)value;
- (void)addBooks:(NSSet<Book *> *)values;
- (void)removeBooks:(NSSet<Book *> *)values;
@end
NS_ASSUME_NONNULL_END
#import "Book.h"
NS_ASSUME_NONNULL_BEGIN
@interface Book (CoreDataProperties)
@property (nullable, nonatomic, retain) NSNumber *rankLastWeek;
@property (nullable, nonatomic, retain) NSNumber *weeksOnList;
@property (nullable, nonatomic, retain) NSString *primaryIsbn10;
@property (nullable, nonatomic, retain) NSString *primaryIsbn13;
@property (nullable, nonatomic, retain) NSString *productUrl;
@property (nullable, nonatomic, retain) NSString *bookImageUrl;
@property (nullable, nonatomic, retain) NSString *publisher;
@property (nullable, nonatomic, retain) NSString *bookDescription;
@property (nullable, nonatomic, retain) NSString *title;
@property (nullable, nonatomic, retain) NSString *contributor;
@property (nullable, nonatomic, retain) NSString *author;
@property (nullable, nonatomic, retain) NSNumber *price;
@end
NS_ASSUME_NONNULL_END