为了更新 iOS 项目中的核心数据模型,我在服务器上查询 JSON 对象,这些对象在某种程度上与我的模型的托管实体相对应。我正在努力的最终结果是来自 JSON 输出的可靠更新解决方案。
对于此问题中的示例,我将命名核心数据管理对象 existingObj和传入的 JSON 反序列化字典 updateDict .棘手的部分是处理这些事实:
existingObj 的所有属性存在于 updateDict updateDict 的所有属性可在 extistingObj 中获得. existingObj的属性与 JSON 反序列化的属性匹配。 (某些字符串可能需要自定义的 Objective-C 包装器)。 updateDict可能包含 nil 中未初始化的键值 ( existingObj ) . 这意味着在迭代更新的字典时,必须来回测试一些属性。首先我要测试
updateDict的属性是否存在于
existingObj ,然后我使用 KVC 设置值,如下所示:
// key is an NSString, e.g. @"displayName"
if ([existingObj respondsToSelector:NSSelectorFromString(key)) {
[existingObj setValue:[updateDict objectForKey:key] forKey:key];
}
虽然这部分有效,但我不喜欢我实际上正在测试
displayName 的事实。作为 setter/getter ,而我将要调用
setDisplayName: setter(间接通过 KVC)。我宁愿是 [existingObj hasWritablePropertyWithName:key] 之类的东西,但我找不到这样做的东西。
这就产生了子问题 A:如果您只有属性的名称,那么如何测试属性 setter ?
下一部分是我想根据它们的类型自动识别属性的地方。如果两者都
updateDict和
existingObj键@"displayName"有一个 NSString,设置新值很容易。但是,如果
updateDict包含键 @"color"的 NSString,即 @"niceShadeOfGreen",我想将其转换为正确的 UIColor 实例。但是如何在
existingObj 中测试接收属性的类型所以我知道什么时候转换值以及什么时候简单地赋值?我希望有类似 typeOfSelector 的东西:
if ([existingObj typeOfSelector:sel] == [[updateDict objectForKey:key] class]) {
// regular assignment
} else {
// perform custom assignment
}
当然,这是伪代码。我不能依赖于测试
existingObj 的类型-property 的值,因为它可能被单元化或
nil .
子问题 B:如果您只有属性(property)的名称,如何测试属性(property)的类型?
我想就是这样。我想这一定是对这里已有的东西的欺骗,但我找不到它。也许你们可以?
干杯,EP。
附言如果您有更好的方法将自定义 Objective-C 对象同步到反序列化的 JSON 对象,请分享!最后,结果才是最重要的。
请您参考如下方法:
如果要查询对象是否具有名为 key 的给定 KVC key 的 setter对应于声明的属性,您需要检查它是否响应名为 setKey: 的选择器方法。 (以 set 开头,将 key 中的第一个字符大写,并添加一个尾随冒号)。例如,
NSString *key = @"displayName";
NSString *setterStr = [NSString stringWithFormat:@"set%@%@:",
[[key substringToIndex:1] capitalizedString],
[key substringFromIndex:1]];
if ([obj respondsToSelector:NSSelectorFromString(setterStr)]) {
NSLog(@"found the setter!");
[obj setValue:someValue forKey:key];
}
两点说明:
set<Key>: 是安全的。因为您使用的是 KVC 来设置相应的值。 -setValue:forUndefinedKey:到接收器,其类可能覆盖了引发异常的标准实现。这在 Key-Value Coding Programming Guide 中有描述.也就是说,如果你总是使用属性,检查 setter 方法应该是安全的。 至于您的第二个问题,无法查询运行时以了解属性的实际 Objective-C 类。从运行时的角度来看, properties 有一个特定于实现的类型编码。和 general types (例如方法参数/返回类型)。这种类型编码对任何 Objective-C 对象使用单一编码(即
@),因此
NSString 的类型编码属性与
UIColor 的类型编码相同属性,因为它们都是 Objective-C 类。
如果您确实需要此功能,另一种方法是处理您的类并添加一个类方法,该方法返回一个字典,其中包含该类和父类(super class)中声明的每个属性(或您感兴趣的属性)的键和相应类型,或者某种描述语言。您必须自己完成此操作,并依赖运行时不可用的信息。




