sas*_*ade 3 objective-c key-value-coding
我有一个对象很可能将NSNull设置为其所有属性的值,并且我正在使用与NSNull值不兼容的代码.有可能覆盖setValue:forKey:在我的对象中这样吗?
-(void)setValue:(id)value forKey:(NSString *)key {
if ([value isEqual:[NSNull null]]) {
[super setValue:nil forKey:key];
} else {
[super setValue:value forKey:key];
}
}
Run Code Online (Sandbox Code Playgroud)
object.property = [NSNull null]在设置它时,不会调用该方法.如何将此设置为我的setter的默认行为?
肯定有办法做到这一点.您可以声明相关属性@dynamic,然后使用+resolveInstanceMethod:按需实际创建setter.您可以在iOS示例代码中找到这样的示例:PTL.此示例演示如何自动使访问者读取和写入字典(properties)而不是来自ivars.为了使这个工作,您可能需要始终存储NSNull在字典中并覆盖getter(propertyIMP())以将其转换为nil.所以你要改变这个:
[[self properties] setValue:value forKey:key];
Run Code Online (Sandbox Code Playgroud)
至:
[[self properties] setValue:(value ?: [NSNull null]) forKey:key];
Run Code Online (Sandbox Code Playgroud)
并改变:
return [[self properties] valueForKey:NSStringFromSelector(_cmd)];
Run Code Online (Sandbox Code Playgroud)
至:
id value = [[self properties] valueForKey:NSStringFromSelector(_cmd)];
return (value == [NSNull null] ? nil : value);
Run Code Online (Sandbox Code Playgroud)
或类似的东西.
但是......除非这是一场重大胜利,否则我会避免这种魔力.我对此的典型解决方案是采用另一种方式,并将其放在呼叫者身上,不[NSNull null]应该在他们不应该通过时.我使用的函数如下RNNonNull():
id RNNonNull(id x) { return (x == [NSNull null]) ? nil : x; }
Run Code Online (Sandbox Code Playgroud)
然后调用者负责添加包装器:
obj.foo = RNNonNull(mystuff);
Run Code Online (Sandbox Code Playgroud)
如果那是不可能的,我可能会手动覆盖getter以转换NSNull为nil而不是使用运行时(它是一行方法).我使用运行时的唯一原因是,如果有一堆属性,并且对象非常简单(纯粹是数据对象).
| 归档时间: |
|
| 查看次数: |
2556 次 |
| 最近记录: |