Restkit 0.2 返回 RKMappingSourceObject 类型对象的一对多类型关系
Posted
技术标签:
【中文标题】Restkit 0.2 返回 RKMappingSourceObject 类型对象的一对多类型关系【英文标题】:Restkit 0.2 returning RKMappingSourceObject type Objects for one-to-many type relationship 【发布时间】:2014-02-10 09:48:49 【问题描述】:我正在尝试在我的应用程序中映射 JSON 数组。我面临的问题是,我得到的不是 NSString 类型的对象,而是 RKMappingSourceObject 类型的对象。
响应格式为
message =
Appetite =
Breakfast = 4;
Dinner = 4;
Lunch = 4;
;
PainSymptom =
Aching = 1;
AtRest = 0;
Awakes = 0;
Burning = 0;
Cramping = 0;
Location = (
Head,
"Right Upper Leg",
"Left Upper Leg",
"Left Ankle/Foot",
"Right Ankle/Foot",
"Mid Back",
"Upper Back",
Tailbone
);
;
我的核心数据类是:
DTAttribute.h
@interface DTAttribute : NSManagedObject
@property (nonatomic, strong) NSString * attribute;
@property (nonatomic, strong) DTPainSymptom *painSymptom;
@end
DTAttribute.m
@implementation DTAttribute
@dynamic attribute;
@dynamic painSymptom;
@end
DTPainSymptom.h
@interface DTPainSymptom : NSManagedObject
@property (nonatomic, retain) NSNumber * aching;
@property (nonatomic, retain) NSNumber * atRest;
@property (nonatomic, retain) NSNumber * awakes;
@property (nonatomic, retain) NSNumber * burning;
@property (nonatomic, retain) NSNumber * cramping;
@property (nonatomic, retain) DTMyDay *myDay;
@property (nonatomic, retain) NSSet *painLocations;
@end
@interface DTPainSymptom (CoreDataGeneratedAccessors)
- (void)addPainLocationsObject:(DTAttribute *)value;
- (void)removePainLocationsObject:(DTAttribute *)value;
- (void)addPainLocations:(NSSet *)values;
- (void)removePainLocations:(NSSet *)values;
@end
DTPainSymptom.m
@implementation DTPainSymptom
@dynamic aching;
@dynamic atRest;
@dynamic awakes;
@dynamic burning;
@dynamic cramping;
@dynamic myDay;
@dynamic painLocations;
@end
DTMyDay.h
@interface DTMyDay : NSManagedObject
@property (nonatomic, retain) DTPainSymptom *painSymptom;
@end
DTMyDay.m
@implementation DTMyDay
@dynamic painSymptom;
@end
映射:
@implementation DTMyDay(映射)
+ (id) mapping
RKEntityMapping* myDayMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([DTMyDay class]) inManagedObjectStore:[[RKObjectManager sharedManager] managedObjectStore]];
RKEntityMapping* attributeMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([DTAttribute class]) inManagedObjectStore:[[RKObjectManager sharedManager] managedObjectStore]];
[attributeMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"attribute"]];
//Pain Symptom
RKEntityMapping* painSymptomMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([DTPainSymptom class]) inManagedObjectStore:[[RKObjectManager sharedManager] managedObjectStore]];
[painSymptomMapping addAttributeMappingsFromDictionary:@
@"Awakes": @"awakes",
@"AtRest": @"atRest",
@"Burning": @"burning",
@"Cramping": @"cramping",
@"Aching": @"aching",
];
[painSymptomMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"Location"
toKeyPath:@"painLocations"
withMapping:attributeMapping]];
[myDayMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"message.PainSymptom"
toKeyPath:@"painSymptom"
withMapping:painSymptomMapping]];
NSDateFormatter* dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:@"yyyy-MM-dd"];
myDayMapping.dateFormatters = [NSArray arrayWithObject: dateFormatter];
return myDayMapping;
+ (id)responseDescriptor:(NSString *)pathPattern
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[self mapping] pathPattern:pathPattern keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
return responseDescriptor;
@end
这里的问题是与message.PainSymptom.Location
对应的值数组未正确映射。我在DTMyDay
类中得到一个与painLocations
对应的DTAttribute 类型对象数组。但是,当我尝试访问 painLocations 数组中每个 DTAttribute 类的属性属性时,我得到的是 RkMappingSourceObject
类型的对象,而不是 NSString
类型的对象。
我很抱歉这堵巨大的代码墙,但现在我真的不知道该怎么办。
这给我带来了一个问题,因为我将 dtAttribute.attribute 发送到一个方法,它返回我 NSNotFound 因为传递的对象是 RKMappingSourceObject 类型:
#define BODY_PARTS_NAMES @"Head", @"Right Shoulder", @"Neck", @"Left Shoulder", @"Right Chest", @"Left Chest", @"Right Arm", nil
- (BodyPart)bodyPartStringToEnum:(NSString *)strVal
NSArray *bodyPartsArray = [[NSArray alloc] initWithObjects:BODY_PARTS_NAMES];
NSUInteger index = [bodyPartsArray indexOfObject:strVal];
return index;
【问题讨论】:
RKMappingSourceObject
代理类给你带来了什么问题?它只是将所有方法调用转发给真正的对象。您是否尝试在某处使用字符串描述(与您期望的相比,这看起来很奇怪)?
我有一个函数,它接受一个 NSString 参数并返回一些值。当我向它发送 dtAttribute.attribute 时,它返回给我 NSNotFound 因为传递的对象是 RKMappingSourceObject 类型。
您能否将该方法的代码添加到您的问题中,我们会考虑修复它吗?
#define BODY_PARTS_NAMES @"头",@"右肩",@"颈",@"左肩",@"右胸",@"左胸",@"右臂" , nil + (BodyPart) bodyPartStringToEnum:(NSString*)strVal NSArray *bodyPartsArray = [[NSArray alloc] initWithObjects:BODY_PARTS_NAMES]; NSUInteger index = [bodyPartsArray indexOfObject:strVal];回报指数;但是,如果 [dtAttribute.attribute mutableCopy] 则一切正常。
【参考方案1】:
RKMappingSourceObject
是 RestKit 内部使用的代理对象,用于处理映射过程中的自省问题和元数据。因为它是一个代理并转发所有方法调用,所以它只是在映射结束时返回。通常这不会导致问题。
我没想到它会根据您的代码引起问题,但显然比较方法中的某些内容不起作用。 RKMappingSourceObject
应该同时转发 class
请求和“正常”方法调用...
RKMappingSourceObject
有一个object
方法,问题是如何知道你应该调用它(因为该类应该作为NSString
的某个子类返回)。我会看一个讨厌的东西,比如:
- (BodyPart)bodyPartStringToEnum:(NSString *)strVal
if ([strVal respondsToSelector:@selector(object)])
strVal = [strVal object];
NSArray *bodyPartsArray = [[NSArray alloc] initWithObjects:BODY_PARTS_NAMES];
NSUInteger index = [bodyPartsArray indexOfObject:strVal];
return index;
我不喜欢它,但希望它能够工作并与将来对代理对象的潜在更改(删除)兼容。或者,调试以确定比较失败的原因并查看更改代理实现。
【讨论】:
我想到了你的解决方法,现在我只是这样做。但是我在代码的其他地方遇到了问题,我在值属性上使用 NSPredicate 过滤了 painSymptom.painLocations(NSSet of DTAttribute) 集。它无法过滤该集合。 因此您可以将该代码移动到自定义访问器方法实现中(因此它始终用于从代理访问object
)。我很想知道为什么代理不起作用,调试可能是最好的方法。可能有另一种使用copy
从代理创建新字符串的替代方法(可能在托管对象子类中)。【参考方案2】:
将RKMappingSourceObject
转换为NSString
的另一种方式:
NSString *realString = [NSString stringWithString:stringProxy];
其中stringProxy
是RKMappingSourceObject
的一个实例。
【讨论】:
以上是关于Restkit 0.2 返回 RKMappingSourceObject 类型对象的一对多类型关系的主要内容,如果未能解决你的问题,请参考以下文章
Restkit 0.2 返回 RKMappingSourceObject 类型对象的一对多类型关系
RestKit 0.2x 同时 RKManagedObjectRequestOperation