ResKit 对象映射嵌套对象
ResKit Object Mapping nested objects
我正在尝试使用 RestKit 来解析一些 JSON。该应用程序用于跟踪比赛,并具有场地、比赛和球员的概念。一场比赛有赢家和输家(class 玩家)和场地。 Web 服务返回的 JSON 如下所示:
[{"id":1,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME3","id":3,"picture_url":"NJ.png"},"venue":{"name":"Venue 1","id":2}},
{"id":2,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME1","id":1,"picture_url":"NC.png"},"venue":{"name":"Venue 1","id":2}},
{"id":3,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME3","id":3,"picture_url":"NJ.png"},"venue":{"name":"Venue 1","id":2}},
{"id":4,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME1","id":1,"picture_url":"NC.png"},"venue":{"name":"Venue 1","id":2}}]
我的对象头文件如下所示:
# PTGame.h
@interface PTGame : NSObject
@property (nonatomic, assign) NSNumber *uid;
@property (nonatomic, assign) PTPlayer *winner;
@property (nonatomic, assign) PTPlayer *loser;
@property (nonatomic, assign) PTVenue *venue;
@end
# PTVenue.h
@interface PTVenue : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSNumber *uid;
-(CLLocation *)location;
-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;
@end
# PTPlayer.h
@interface PTPlayer : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *pictureUrl;
@property (nonatomic, assign) NSNumber *uid;
@end
最后,我的映射设置如下所示:
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping *venueMapping = [RKObjectMapping mappingForClass:[PTVenue class]];
[venueMapping addAttributeMappingsFromDictionary:@{@"name" : @"name",
@"id" : @"uid"}];
RKObjectMapping *playerMapping = [RKObjectMapping mappingForClass:[PTPlayer class]];
[playerMapping addAttributeMappingsFromDictionary:@{@"name" : @"name",
@"id" : @"uid",
@"picture_url": @"pictureUrl"}];
// Add Object Mapping for PTGame
RKObjectMapping *gameResponseMapping = [RKObjectMapping mappingForClass:[PTGame class]];
// Setup Game Object relationships
[gameResponseMapping addAttributeMappingsFromDictionary:@{@"id": @"uid"}];
[gameResponseMapping addRelationshipMappingWithSourceKeyPath:@"winner" mapping:playerMapping];
[gameResponseMapping addRelationshipMappingWithSourceKeyPath:@"loser" mapping:playerMapping];
[gameResponseMapping addRelationshipMappingWithSourceKeyPath:@"venue" mapping:venueMapping];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *gameListResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:gameResponseMapping
method:RKRequestMethodGET
pathPattern:@"/games.json"
keyPath:nil
statusCodes:statusCodes];
[objectManager addResponseDescriptor:gameListResponseDescriptor];
我觉得这一切都很合适。返回结果时没有抛出任何错误,但后来我在尝试访问游戏的 属性 时遇到异常。通过 XCode 调试器查看对象显示:
似乎有什么地方坏了 - 为什么这些字符串显示为 "winner" 和 "venue"。为什么 uid
为空?每次我发出请求时对象看起来都不一样,让我相信内存没有被正确处理。
有什么想法吗?
Wain's comment led me down the path of looking outside of the mapping code. I looked in the RestKit Object Mapping docs 并注意到所有属性都使用了 nonatomic
和 copy
属性,而不是 assign
。此外,对象引用(例如 PTPlayer *winner
只是 nonatomic
。更改我的代码以反映此问题已解决。
生成的头文件如下所示:
# PTPlayer.h
@interface PTPlayer : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *pictureUrl;
@property (nonatomic, copy) NSNumber *uid;
@end
# PTVenue.h
@interface PTVenue : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSNumber *uid;
@property (nonatomic, assign) CGFloat longitude;
@property (nonatomic, assign) CGFloat latitude;
-(CLLocation *)location;
-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;
@end
# PTGame.h
@interface PTGame : NSObject
@property (nonatomic, copy) NSNumber *uid;
@property (nonatomic) PTPlayer *winner;
@property (nonatomic) PTPlayer *loser;
@property (nonatomic) PTVenue *venue;
@end
我正在尝试使用 RestKit 来解析一些 JSON。该应用程序用于跟踪比赛,并具有场地、比赛和球员的概念。一场比赛有赢家和输家(class 玩家)和场地。 Web 服务返回的 JSON 如下所示:
[{"id":1,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME3","id":3,"picture_url":"NJ.png"},"venue":{"name":"Venue 1","id":2}},
{"id":2,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME1","id":1,"picture_url":"NC.png"},"venue":{"name":"Venue 1","id":2}},
{"id":3,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME3","id":3,"picture_url":"NJ.png"},"venue":{"name":"Venue 1","id":2}},
{"id":4,"winner":{"name":"NAME2","id":2,"picture_url":"CK.png"},"loser":{"name":"NAME1","id":1,"picture_url":"NC.png"},"venue":{"name":"Venue 1","id":2}}]
我的对象头文件如下所示:
# PTGame.h
@interface PTGame : NSObject
@property (nonatomic, assign) NSNumber *uid;
@property (nonatomic, assign) PTPlayer *winner;
@property (nonatomic, assign) PTPlayer *loser;
@property (nonatomic, assign) PTVenue *venue;
@end
# PTVenue.h
@interface PTVenue : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSNumber *uid;
-(CLLocation *)location;
-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;
@end
# PTPlayer.h
@interface PTPlayer : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *pictureUrl;
@property (nonatomic, assign) NSNumber *uid;
@end
最后,我的映射设置如下所示:
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping *venueMapping = [RKObjectMapping mappingForClass:[PTVenue class]];
[venueMapping addAttributeMappingsFromDictionary:@{@"name" : @"name",
@"id" : @"uid"}];
RKObjectMapping *playerMapping = [RKObjectMapping mappingForClass:[PTPlayer class]];
[playerMapping addAttributeMappingsFromDictionary:@{@"name" : @"name",
@"id" : @"uid",
@"picture_url": @"pictureUrl"}];
// Add Object Mapping for PTGame
RKObjectMapping *gameResponseMapping = [RKObjectMapping mappingForClass:[PTGame class]];
// Setup Game Object relationships
[gameResponseMapping addAttributeMappingsFromDictionary:@{@"id": @"uid"}];
[gameResponseMapping addRelationshipMappingWithSourceKeyPath:@"winner" mapping:playerMapping];
[gameResponseMapping addRelationshipMappingWithSourceKeyPath:@"loser" mapping:playerMapping];
[gameResponseMapping addRelationshipMappingWithSourceKeyPath:@"venue" mapping:venueMapping];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *gameListResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:gameResponseMapping
method:RKRequestMethodGET
pathPattern:@"/games.json"
keyPath:nil
statusCodes:statusCodes];
[objectManager addResponseDescriptor:gameListResponseDescriptor];
我觉得这一切都很合适。返回结果时没有抛出任何错误,但后来我在尝试访问游戏的 属性 时遇到异常。通过 XCode 调试器查看对象显示:
似乎有什么地方坏了 - 为什么这些字符串显示为 "winner" 和 "venue"。为什么 uid
为空?每次我发出请求时对象看起来都不一样,让我相信内存没有被正确处理。
有什么想法吗?
Wain's comment led me down the path of looking outside of the mapping code. I looked in the RestKit Object Mapping docs 并注意到所有属性都使用了 nonatomic
和 copy
属性,而不是 assign
。此外,对象引用(例如 PTPlayer *winner
只是 nonatomic
。更改我的代码以反映此问题已解决。
生成的头文件如下所示:
# PTPlayer.h
@interface PTPlayer : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *pictureUrl;
@property (nonatomic, copy) NSNumber *uid;
@end
# PTVenue.h
@interface PTVenue : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSNumber *uid;
@property (nonatomic, assign) CGFloat longitude;
@property (nonatomic, assign) CGFloat latitude;
-(CLLocation *)location;
-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;
@end
# PTGame.h
@interface PTGame : NSObject
@property (nonatomic, copy) NSNumber *uid;
@property (nonatomic) PTPlayer *winner;
@property (nonatomic) PTPlayer *loser;
@property (nonatomic) PTVenue *venue;
@end