在 Objective-C 中只写属性
Posted
技术标签:
【中文标题】在 Objective-C 中只写属性【英文标题】:Write only property in Objective-C 【发布时间】:2011-05-15 01:13:33 【问题描述】:我被 Objective-c 属性卡住了。我需要为变量分配一个只写属性,与只读相反,即变量可以有setMethod
,但它不应该有getMethod
。我不知道该怎么做。感谢您提供一些代码 sn-ps 的答案。
【问题讨论】:
只写属性有什么用?恕我直言,这只是浪费内存。 用途广泛;通常,当您希望某些内容是公开的只写和内部的类时,它是可读写的。 当外部类知道需要传入的变量但没有理由知道它当前设置为什么时。 【参考方案1】:是否有任何理由需要将其作为属性?我只是将 setter 声明为方法并使用普通的[foo setVar:bar]
语法。
【讨论】:
是的,这行得通,但 xCode 似乎不会在您键入时自动完成 var。 @FredrikJohansson 你是对的。对于自动完成友好的解决方案,您可能需要查看我的解决方案。【参考方案2】:你可以这样做:
@interface MyClass
@private
int _var;
- (void)setVar:(int)newVar;
@end
@implementation MyClass
- (void)setVar:(int)newVar
_var = newVar;
@end
现在您可以访问变量var
,就像一个只写属性:
@implementation SomeOtherClass
...
MyClass c = [[MyClass alloc] init];
c.var = 3;
...
@end
如果您尝试读取虚假属性,编译器会警告您。
【讨论】:
需要在实现和接口中定义一个方法-(void)setVar:(int)newVar
。
@kubbing 从技术上讲,它是一个属性。 Obj-C 中的属性只是 getter 和 setter 这两种方法的花哨名称。您可以在不使用@property
的情况下声明getter,其行为将与@property
完全相同。这同样适用于二传手。您甚至可以使用点符号。
@Sulthan 这几乎是正确的,部分原因是运行时做出了这种区分。例如,像这样的 fake 属性在使用 class_copyPropertyList
时不会被列出。请参阅我的答案以了解不同的方法。
@Sulthan 同意。可能我的解决方案的最大优势是自动完成(而且它也更短;))。
如果你在 Swift 中使用这个类,让它成为一个真实的属性会有所不同。如果它不是属性,则不能在 Swift 中使用点表示法。【参考方案3】:
另一种有效的方法是声明普通属性并使 getter 不可用
@interface MyClass
@property NSString * var;
- (NSString *)var UNAVAILABLE_ATTRIBUTE;
@end
如果有人试图访问 getter,这将引发编译时错误。
这种方法的主要优点是您实际上有一个真实属性TM,而不是由实例变量和设置器伪造的代理项,这意味着:
在 Xcode 中使用点表示法时会自动完成 所有运行时函数,例如class_getProperty
和
class_copyPropertyList
将按预期工作。
也就是说,无论如何,getter 实现都是合成的,可以使用类似的方法调用它
NSString * string = [myObj performSelector:@selector(var)];
或使用NSInvocation
(如果是非id
属性)
如果您偏执并且真的想要阻止客户端调用 getter,则可以通过提供自己的实现来显式抛出异常。
@implementation MyClass
- (int)var
[NSException raise:NSInternalInconsistencyException
format:@"property is write-only"];
@end
无论如何,如果有人真的想篡改您的实例变量,他们可以使用运行时来访问它,因此考虑到用例,最后的预防措施可能是无用的。编译时错误才是您真正要寻找的。p>
【讨论】:
LLVM 可以使用它吗?以上是关于在 Objective-C 中只写属性的主要内容,如果未能解决你的问题,请参考以下文章