Sam*_*ett 3 cocoa objective-c key-value-coding
如果我只有一个键列表,是否有一种优雅的方法来测试对象的只读与读/写属性?我意识到我可以把钥匙串起来:
NSString *setterString = [@"set" stringByAppendingString:[someKeyString capitalizedString]];
BOOL isReadWrite = [myObject respondsToSelector:NSSelectorFromString(setterString)];
Run Code Online (Sandbox Code Playgroud)
或者更好的是尝试为密钥设置一个值并检查NSUndefinedKeyException
- 但是对非异常行为使用异常似乎是不好的形式.
为了清楚起见,我想以编程方式审计对象的属性,并告诉它们之间的区别,例如,
@property (readonly) NSString *someReadOnlyKey
@property NSString *someReadWriteProperty
Run Code Online (Sandbox Code Playgroud)
编辑:为了更清楚,如果将键实现为@property
s或手动getter/setter ,则无关紧要.只关注公共接口.并且感谢您询问我想要实现的目标 - 首先要做到这一点可能更为重要.
我试图勾勒出一些生成对象键的图形表示的代码.所有的密钥都是事先知道的 - 但我不会总是知道哪些密钥可以建立(这取决于特定的子类实现)
您有两种有效的方法:
respondsToSelector:
方法我将尝试总结两种方法的含义及其缺点.然后,您可以选择更适合您需求的方法.
//MyClass.h
@property (readonly) NSString *someReadOnlyKey;
Run Code Online (Sandbox Code Playgroud)
好的,一切都按预期工作.
//MyClass.h
@property (readonly) NSString *someReadOnlyKey;
///////////////////////////////////////////////////////////////////////////
//MyClass.m
@property (readwrite) NSString *someReadOnlyKey;
Run Code Online (Sandbox Code Playgroud)
如果已覆盖属性定义,则将获得正在使用的实际属性属性.无论您是从setter可见的位置(即在类定义中)还是从外部查询它都无关紧要.您将获得用于合成访问器方法的实际定义.
//MyClass.h
@property (setter=myCoolSetter) NSString *someReadOnlyKey;
Run Code Online (Sandbox Code Playgroud)
使用自定义setter名称,该respondsToSelector
技巧将不再起作用,而运行时仍然提供正确的信息.
//MyClass.h
@property (readonly) NSString *someReadOnlyKey;
///////////////////////////////////////////////////////////////////////////
//MyClass.m
- (void)setSomeReadOnlyKey:(NSString *)someReadOnlyKey {
_someReadOnlyKey = someReadOnlyKey;
}
Run Code Online (Sandbox Code Playgroud)
这次运行时失败,因为setter在那里,但属性定义"不知道"它.
假设您可以询问元类(即,您不希望允许针对调度表的潜在特定于实例的修补程序),您可以从运行时获取属性属性.特别:
// get the property; yes: that's a C string. This can see only things
// declared as @property
objc_property_t property =
class_getProperty([instance class], "propertyName");
/* check property for NULL here */
// get the property attributes.
const char *propertyAttributes = property_getAttributes(property);
Run Code Online (Sandbox Code Playgroud)
然后,您可以检查这些属性是否为只读:
NSArray *attributes =
[[NSString stringWithUTF8String:propertyAttributes]
componentsSeparatedByString:@","];
return [attributes containsObject:@"R"];
Run Code Online (Sandbox Code Playgroud)
如果你想要完全彻底,你也应该通过class_copyProtocolList
和检查协议protocol_getProperty
,以便捕获任何@property
以这种方式被纳入课程的内容,并且 - 如下面由Gabriele所述 - 一些警告适用于类扩展.
归档时间: |
|
查看次数: |
1283 次 |
最近记录: |