在Objective-C中只写属性

Kin*_*ven 29 iphone properties objective-c accessor iphone-sdk-3.0

我坚持使用objective-c属性.我需要的是为变量分配一个只写属性,与readonly完全相反,即变量可以有setMethod,但它不应该有getMethod.我不知道怎么做.一些代码片段的答案表示赞赏.

Gab*_*lla 50

另一种有效的方法是声明普通属性并使getter不可用

@interface MyClass
@property NSString * var;
- (NSString *)var UNAVAILABLE_ATTRIBUTE;
@end
Run Code Online (Sandbox Code Playgroud)

如果有人试图访问getter,这将引发编译时错误.


这种方法的主要优点是你实际上有一个不动产TM而不是由实例变量和一个setter伪造的代理,这意味着:

  • 在Xcode中使用点符号时,您将获得自动完成功能
  • 所有运行时函数,如class_getPropertyclass_copyPropertyList将按预期工作.

也就是说,无论如何都会合成getter实现,并且可以使用类似的东西调用它

NSString * string = [myObj performSelector:@selector(var)];
Run Code Online (Sandbox Code Playgroud)

或使用NSInvocation(如果是非id财产)

如果你是偏执狂并且你真的想阻止客户端调用getter,你可以通过提供自己的实现来显式抛出异常.

@implementation MyClass
- (int)var {
    [NSException raise:NSInternalInconsistencyException
                format:@"property is write-only"];
}
@end
Run Code Online (Sandbox Code Playgroud)

无论如何,如果有人真的想要篡改你的实例变量,他们可以使用运行时来访问它,所以考虑到用例,最后的预防措施可能是无用的.您正在寻找编译时错误.


Bru*_*sso 12

你可以这样做:

@interface MyClass {
@private
int _var;
}

- (void)setVar:(int)newVar;
@end

@implementation MyClass
- (void)setVar:(int)newVar {
_var = newVar;
}
@end
Run Code Online (Sandbox Code Playgroud)

现在,您可以var像只写的属性一样访问变量:

@implementation SomeOtherClass
...
MyClass c = [[MyClass alloc] init];
c.var = 3;
...
@end
Run Code Online (Sandbox Code Playgroud)

如果你试图读取假属性,编译器会警告你.

  • 它不是财产 (4认同)
  • @kubbing从技术上讲,这是一个财产.Obj-C中的一个属性只是两个方法的一个奇特名称,getter和setter.您可以在不使用`@ property`的情况下声明getter,其行为与`@ property`完全相同.这同样适用于二传手.您甚至可以使用点符号. (4认同)
  • @Sulthan这几乎是正确的,这是运行时进行区分的一部分.使用`class_copyPropertyList`时,不会列出像这样的*fake*属性.请参阅我的答案,了解不同的方法. (2认同)
  • 如果你在 Swift 中使用这个类,让它成为一个真正的属性会有所不同。如果它不是属性,则不能在 Swift 中使用点符号。 (2认同)

gra*_*rks 5

这有什么理由需要成为财产吗?我只是将setter声明为方法并使用普通[foo setVar:bar]语法.

  • 或者使用点语法...`foo.var = bar;`仍然有效. (5认同)