Ale*_*lex 89 properties objective-c readonly
我在我的界面中声明了一个readonly属性:
@property (readonly, nonatomic, copy) NSString* eventDomain;
Run Code Online (Sandbox Code Playgroud)
也许我误解了属性,但我认为当你声明它时readonly
,你可以在implementation(.m
)文件中使用生成的setter ,但是外部实体不能改变它的值.这个问题说的是应该发生的事情.这就是我追求的行为.但是,当尝试使用标准setter或dot语法设置eventDomain
我的init方法时,它会给我一个unrecognized selector sent to instance.
错误.我当然是@synthesize
属于该物业.试着像这样使用它:
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
Run Code Online (Sandbox Code Playgroud)
我是否误解readonly
了财产上的声明?或者还有其他事情发生了吗?
Eik*_*iko 111
您需要告诉编译器您还需要一个setter.一种常见的方法是将它放在.m文件中的类扩展中:
@interface YourClass ()
@property (nonatomic, copy) NSString* eventDomain;
@end
Run Code Online (Sandbox Code Playgroud)
yan*_*ano 36
我发现使用readonly属性的另一种方法是使用@synthesize指定后备存储.例如
@interface MyClass
@property (readonly) int whatever;
@end
Run Code Online (Sandbox Code Playgroud)
然后在实施中
@implementation MyClass
@synthesize whatever = m_whatever;
@end
Run Code Online (Sandbox Code Playgroud)
然后你的方法可以设置_whatever,因为它是一个成员变量.
我在过去几天中意识到的另一个有趣的事情是,您可以创建可由子类写入的只读属性,例如:
(在头文件中)
@interface MyClass
{
@protected
int m_propertyBackingStore;
}
@property (readonly) int myProperty;
@end
Run Code Online (Sandbox Code Playgroud)
然后,在实施中
@synthesize myProperty = m_propertyBackingStore;
Run Code Online (Sandbox Code Playgroud)
它将在头文件中使用声明,因此子类可以更新属性的值,同时保留其readonlyness.
稍微遗憾的是,在数据隐藏和封装方面.
Bas*_*que 35
Eiko和其他人给出了正确的答案.
这是一种更简单的方法:直接访问私有成员变量.
例
在标题.h文件中:
@property (strong, nonatomic, readonly) NSString* foo;
在实现.m文件中:
// inside one of my init methods
self->_foo = @"someString"; // Notice the underscore prefix of var name.
Run Code Online (Sandbox Code Playgroud)
就是这样,这就是你所需要的.没有麻烦,没有大惊小怪.
细节
从Xcode 4.4和LLVM Compiler 4.0(Xcode 4.4中的新功能)开始,您不必搞乱其他答案中讨论的杂事:
synthesize
关键字在声明属性之后foo
,您可以假设Xcode添加了一个名为前缀为underscore的私有成员变量:_foo
.
如果声明了属性readwrite
,Xcode会生成一个名为getter的方法foo
和一个名为的setter setFoo
.使用点表示法(我的Object.myMethod)时会隐式调用这些方法.如果声明了属性readonly
,则不会生成setter.这意味着以下划线命名的支持变量本身并不是只读的.的readonly
仅仅是没有setter方法合成,因此使用点符号设定值的装置失败,编译错误.点表示法失败,因为编译器阻止您调用不存在的方法(setter).
最简单的方法是直接访问使用下划线命名的成员变量.即使没有声明下划线命名变量,您也可以这样做!Xcode将该声明作为构建/编译过程的一部分插入,因此您的编译代码确实具有变量声明.但是您从未在原始源代码文件中看到该声明.不是魔术,只是语法糖.
使用self->
是一种访问对象/实例的成员变量的方法.您可以省略它,只使用var名称.但我更喜欢使用self + arrow,因为它使我的代码自我记录.当你看到self->_foo
你知道_foo
这个实例上没有歧义的成员变量时.
顺便说一下,讨论物业访问者与直接ivar访问的利弊,正是Matt Neuberg博士的iOS编程书中你会想到的那种深思熟虑的处理方式.我发现阅读和重读非常有帮助.
你误解了另一个问题.在那个问题中有一个类扩展,声明如下:
@interface MYShapeEditorDocument ()
@property (readwrite, copy) NSArray *shapesInOrderBackToFront;
@end
Run Code Online (Sandbox Code Playgroud)
这就是生成只在类的实现中可见的setter的原因.因此,正如Eiko所说,您需要声明一个类扩展并覆盖属性声明,以告诉编译器仅在类中生成一个setter.
最短的解决方案是:
MyClass.h
@interface MyClass {
int myProperty;
}
@property (readonly) int myProperty;
@end
Run Code Online (Sandbox Code Playgroud)
MyClass.h
@implementation MyClass
@synthesize myProperty;
@end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
85754 次 |
最近记录: |