我有以下代码:
-(id) initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
self = [super init];
if (self)
{
coordinate = c;
self.title = t;
}
return self;
}
其中coordinate
是:
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
我有两个问题:
coordinate
之前有self
吗? (例如,self.coordinate = c
)。PS。我使用这段代码没有任何错误 - 这是一本书的例子。
答案 0 :(得分:15)
你应该写:self.coordinate = c
等于[self setCoordinate:c]
- 调用setter方法。但是你不能这样做,因为你会得到Assignment to readonly property
错误。只读属性没有setter方法。在你的情况下,你只需设置直接支持属性的ivar,它是记录良好的行为。 ivar
名称将是前缀为下划线的属性名称,因为在您的情况下,如您所说,您有一个明确的@synthesize
,因此ivar将具有相同的名称,这就是为什么您没有任何名称编译问题。该属性可以是只读的,但可以由类写入 - 这涉及在类扩展中声明setter方法或在扩展中重新声明属性。为此,您可以参考以下帖子:Objective-C property that is readonly publicly, but has a private setter
答案 1 :(得分:3)
可以分配给只读的属性吗?
是的,如果您不希望在其包含的实例之外更改属性,则可以。
例如:数组的count属性,这里count是一个依赖于数组保留的对象数的属性。所以不应该从Array对象外面修改它。
之前不应该协调自己吗? (例如,self.coordinate = c)。
如果只读,则无法通过setter方法修改属性。
self.coordinate转换为[self setCoordinate:],这是不允许的,只允许setter方法修改属性。
所以你应该直接设置ivar
,这只能从定义了readonly属性的对象内部完成。
即
_coordinate = value; //or coordinate = value if you have synthesized it.
如果你很好奇,
self.propertyName && self.property = indirectly calls getter and setter method.
在实施过程中,setter和getter帮助_ivars公开 - 可以访问公共财产。
- (void)setProperty(value) //self.property = value
{
_property = value;
}
- (id)property //self.property
{
return _property;
}
答案 2 :(得分:1)
您无法使用readonly属性为变量赋值,但是从iOS6开始,可以自动添加@synthesize,因此您可以使用ivar替换它。喜欢 _test = @“test”替换self.test = @“test”如果test的属性是readonly。
答案 3 :(得分:0)
不,那不行。分配readonly
的正确方法是这样的:
- (CLLocationCoordinate2D)coordinate {
//create the struct and return it.
return value;
}
不,不是相反。您应该像这样设置title
:
_title = t;
答案 4 :(得分:0)
行coordinate = c;
未分配属性,它正在分配具有相同名称的实例变量。无法分配只读属性,这就是“只读”的含义。如果将其更改为self.coordinate = c
,则会出现错误,除非在类扩展中将此属性重新声明为readwrite。
答案 5 :(得分:0)
可以分配给只读的属性吗?
如果你使用像你一样的合成访问器,那就完全没问题了。
之前不应该协调自己吗? (例如,self.coordinate = c)。
self.coordinate是非合成访问器的快捷方式。这个setter在类外部是可见的,因此对于类用户来说,该属性应该是只读的,如果尝试使用点表示法访问readonly属性,则会出现编译器错误。你的代码是正确的。
答案 6 :(得分:0)
可以分配给只读的属性吗?
如果您@synthesize coordinate;
,则支持ivar将命名为coordinate
。如果属性是自动合成的,则会将其命名为_coordinate
。
如果您的意图是在初始化程序中分配基础实例变量,那就没问题(例如coordinate = c
或_coordinate = c
)。
如果你想使用setter设置它(例如[self setCoordinate:c]
或self.coordinate = c;
,你需要自己实现setter或合成它的定义(例如通过在类继续中声明属性readwrite)。
之前不应该协调自己吗? (例如,self.coordinate = c)。
不,it should not。在部分构造的状态下使用直接访问,例如初始化程序或-dealloc
。
鉴于属性:
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy, readwrite) NSString * title;
您的初始化程序应采用以下形式:
- (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
self = [super init];
if (self)
{
_coordinate = c;
_title = t.copy; // note: copy/ownership semantics match property declaration
}
return self;
}
@end
答案 7 :(得分:0)
我见过狡猾的人这样做....
Source.h
@property (readonly) BOOL isRunning;
Source.m
- (void) blahBlahBlah { ...
self->_isRunning = YES; ...
我可以找到关于这些类型的访问器的文档很少...我很确定它只是一个标准的C构造...我不是很熟悉...但这是一种方式如果你掌握了这个主题......比我的好......