分配只读属性

13
我有以下代码:
-(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. 我使用这段代码没有任何错误——它是一本书中的例子。


1
如果你有一个只读属性,你就不能给它赋任何值,编译器会在这种情况下报错。 - Suryakant Sharma
当你给一个只读属性赋值时,应该会出现编译问题,这是因为它在其他地方被设置成了可读写吗?你是否正在合成? - Wain
@Wain:是的,我进行了合成。我没有遇到编译器问题。 - user2568508
1
在初始化方法中不应使用属性:http://qualitycoding.org/objective-c-init/ - vikingosegundo
1
请在此处查看链接:http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html%23//apple_ref/doc/uid/TP40011210-CH5-SW11 - vikingosegundo
显示剩余3条评论
8个回答

16
你应该编写:self.coordinate = c,等同于调用 setter 方法的 [self setCoordinate:c]。但你不能这样做,因为会得到 Assignment to readonly property 的错误提示。只读属性没有 setter 方法。在你的情况下,你只是直接设置了支持属性的 ivar,这是一个被很好地记录的行为。ivar 的名称将以下划线为前缀,后面跟着属性名称,但是在你的情况下你有一个明确的 @synthesize 声明,所以 ivar 将具有相同的名称,这就是你没有任何编译问题的原因。属性可以在公共上是只读的,但在类中可写 - 这涉及在类扩展中声明 setter 方法或重新声明属性。有关详细信息,请参阅此 post:Objective-C property that is readonly publicly, but has a private setter

他正在使用合成的setter。 - Ramy Al Zuhouri

3
  • 只读属性可以赋值吗?

    可以,如果你不想让一个属性在其实例外被修改。

    例如:数组的count属性,它依赖于数组中保留的对象数量。因此,它不应该从Array对象外部进行修改。

  • self.coordinate之前是否应该加上self?(例如,self.coordinate = c)

    如果是只读的,你不能通过setter方法修改属性。

    self.coordinate相当于[self setCoordinate:],只读属性防止setter方法修改属性,因此这种写法是不允许的。

所以你应该直接设置ivar,而这只能从定义只读属性的对象内部完成。

_coordinate = value; //or coordinate = value if you have synthesized it. 

如果您好奇,
self.propertyName && self.property = indirectly calls getter and setter method.

在实现中,如果属性是公共的,那么设置器和获取器可以帮助_ivars被公开访问。

- (void)setProperty(value) //self.property = value
 {
    _property = value;
 }

- (id)property  //self.property
  {
     return _property;
  }

我明白了,所以在 Obj. C 中直接引用实例变量也是可以的,对吧,例如 myVariable = 13;(不需要使用 self)。 - user2568508
除非您已经使用 @synthesized,否则您无法这样做。否则,您需要将其称为 _varName。 - egghese

1

您不能为具有只读属性的变量分配值,但是从iOS6开始,@synthesize可以自动添加,因此您可以使用ivar替换它。例如,如果test属性是只读的,则可以使用_test = @"test"来替换self.test = @"test"。


0

我见过一些狡猾的人这样做...

Source.h

@property (readonly) BOOL  isRunning;

Source.m

- (void) blahBlahBlah { ...
   self->_isRunning = YES; ...

我找到的有关这些类型访问器的文档非常少... 我相当确定这仅仅是标准的C结构... 这是一种方法,适用于你精通这个主题,而我并不是很熟悉...


0
  1. 不,那样是不对的。赋值readonly的正确方法如下:

    - (CLLocationCoordinate2D)coordinate {
    
        //创建结构体并将其返回。
    
        返回值;
    
    }
    
  2. 不,应该是另一种方式。您应该像这样设置title

    _title = t;
    

0

给只读属性赋值是否可以?

如果你使用@synthesize coordinate;,那么后备的ivar将被命名为coordinate。如果该属性是自动合成的,则将命名为_coordinate

如果您的意图是在初始化器中分配给底层实例变量,那么这是可以的(例如coordinate = c_coordinate = c)。

如果您想使用setter设置它(例如[self setCoordinate:c]self.coordinate = c;),则需要自己实现setter或合成其定义(例如通过在类延续中声明属性readwrite)。


“coordinate”之前应该加上“self”吗?(例如,self.coordinate = c)。
不需要,不需要。在部分构造状态下,例如初始化程序或-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

0

代码行 coordinate = c; 并没有赋值给属性,而是赋值给了同名的实例变量。无法给只读属性赋值,这就是“只读”的含义。如果你将其改为 self.coordinate = c,除非在类扩展中重新声明该属性为可读写,否则会出现错误。


0
这段内容与编程有关:
“给只读属性赋值是否可以?”
如果您像您正在做的那样使用合成访问器,那么完全没有问题。
“在协调之前不应该加上self吗?(例如,self.coordinate = c)。”
self.coordinate是非合成访问器的快捷方式。此setter可从类外部访问,因此,由于属性对于类用户应为只读,如果您尝试使用点符号访问只读属性,则会收到编译器错误。您的代码是正确的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接