ios 分配只读属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17721724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:23:16  来源:igfitidea点击:

Assigning readonly property

iosobjective-c

提问by Oleksandr Karaberov

I have following code:

我有以下代码:

-(id) initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
    self = [super init];

    if (self)
    {
        coordinate = c;
        self.title = t;
    }

    return self;
}

where coordinateis:

在哪里coordinate

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

I had two questions:

我有两个问题:

  • is it OK to assign to a property that is readonly?
  • should not coordinatehave selfbefore it? (e.g., self.coordinate = c).
  • 可以分配给只读属性吗?
  • 不应该coordinateself前呢?(例如,self.coordinate = c)。

ps. I don't get any errors using this code - and it is an example from a book.

附:使用此代码我没有遇到任何错误 - 这是书中的一个例子。

回答by Oleksandr Karaberov

You should write: self.coordinate = cwhich is equal to [self setCoordinate:c]- calling setter method. But you can't do this because you will get Assignment to readonly propertyerror. Read-only properties don't have setter methods.In your case you just set the ivar which backs the property directly and it is well documented behavior. The ivarname will be the property name prefixed with an underscore BUT as in your case you have an explicit @synthesizeas you said, so the ivar will have the same name and that's why you haven't any compiler issues. It is possible for the property to be read-only publicly, but be writeable by the class - this involves either declaring a setter method in a class extension or redeclaring the property in the extension. For this you can refer this post: Objective-C property that is readonly publicly, but has a private setter

你应该写:self.coordinate = c这等于[self setCoordinate:c]- 调用 setter 方法。但是你不能这样做,因为你会得到Assignment to readonly property错误。只读属性没有 setter 方法。在您的情况下,您只需设置直接支持该属性的 ivar,这是有据可查的行为。该ivar名称将是带有下划线前缀的属性名称,但在您的情况下,您有一个明确@synthesize的名称,因此 ivar 将具有相同的名称,这就是为什么您没有任何编译器问题的原因。属性可能是公开只读的,但可由类写入 - 这涉及在类扩展中声明 setter 方法或在扩展中重新声明属性。为此,您可以参考这篇文章:公开只读但具有私有 setter 的 Objective-C 属性

回答by Jesly Varghese

  • is it OK to assign to a property that is readonly?

    Yes, its okay if you don't want a property to be mutated outside its containing instance.

    eg: count property of an array, here count is a property that is dependent on the number of objects retained by the array. So it shouldn't be modified from outside the Array object.

  • should not coordinate have self before it? (e.g., self.coordinate = c).

    If read only, you can't modify your property via a setter method.

    self.coordinate translates to [self setCoordinate:] which is not permitted as read only prevents setter methods from modifying the property.

  • 可以分配给只读属性吗?

    是的,如果您不希望属性在其包含的实例之外发生变异,那也没关系。

    eg:数组的count属性,这里count是一个依赖于数组保留的对象数量的属性。因此不应从 Array 对象外部修改它。

  • 不应该协调之前有自我吗?(例如,self.coordinate = c)。

    如果只读,则无法通过 setter 方法修改属性。

    self.coordinate 转换为 [self setCoordinate:],这是不允许的,因为只读会阻止 setter 方法修改属性。

So you should directly set the ivar, and this can be done only from inside the object for which readonly property is defined.

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

i.e

IE

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

If you are curious,

如果你好奇,

self.propertyName && self.property = indirectly calls getter and setter method.

And in implementation, setters and getter help the _ivars to be public-ally accessible is the property is public.

在实现中,setter 和 getter 帮助 _ivars 可以公开访问,因为属性是公开的。

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

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

回答by harryyan

you cannot assign value to variable with readonly property, but from iOS6, the @synthesize can be added automatically, so you can use ivar to replace it. Like _test = @"test" to replace self.test = @"test" if the property of test is readonly.

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

回答by Desdenova

  1. No that is not ok. Proper way to assign readonlyis like this:

    - (CLLocationCoordinate2D)coordinate {
    
        //create the struct and return it.
    
        return value;
    
    }
    
  2. No it is the other way around. You should set titlelike this:

    _title = t;
    
  1. 不,那不行。正确的赋值方式readonly是这样的:

    - (CLLocationCoordinate2D)coordinate {
    
        //create the struct and return it.
    
        return value;
    
    }
    
  2. 不,相反。你应该这样设置title

    _title = t;
    

回答by hamstergene

The line coordinate = c;is not assigning the property, it's assigning the instance variable which has the same name. It is not possible to assign a readonly property, that's what “read only” means. If you change it to self.coordinate = cyou will get an error, unless this property is redeclared as readwrite in class extension.

该行coordinate = c;不是分配属性,而是分配具有相同名称的实例变量。不可能分配只读属性,这就是“只读”的意思。如果将其更改为self.coordinate = c您将收到错误,除非在类扩展中将此属性重新声明为 readwrite。

回答by Ramy Al Zuhouri

is it OK to assign to a property that is readonly?

可以分配给只读属性吗?

If you use synthesized accessors like you're doing, it's perfectly fine.

如果您像现在一样使用合成访问器,那完全没问题。

should not coordinate have self before it? (e.g., self.coordinate = c).

不应该协调之前有自我吗?(例如,self.coordinate = c)。

self.coordinate is a shortcut for the non synthesized accessor. This setter is visible from outside the class, so since the property should be readonly for class users, you get a compiler error if you try to access readonly properties with the dot notation. Your code is correct.

self.coordinate 是非合成访问器的快捷方式。这个 setter 是从类外部可见的,因此由于该属性对于类用户应该是只读的,如果您尝试使用点表示法访问只读属性,则会出现编译器错误。你的代码是正确的。

回答by justin

is it OK to assign to a property that is readonly?

可以分配给只读属性吗?

If you @synthesize coordinate;, then the backing ivar will be named coordinate. If the property is auto-synthesized, it will be named _coordinate.

如果是@synthesize coordinate;,则支持的 ivar 将被命名coordinate。如果属性是自动合成的,它将被命名为_coordinate

If your intent is to assign to the underlying instance variable within the initializer, that is fine (e.g. coordinate = cor _coordinate = c).

如果您的意图是分配给初始化程序中的底层实例变量,那很好(例如coordinate = c_coordinate = c)。

If you want to set it using the setter (e.g. [self setCoordinate:c]or self.coordinate = c;you would need to implement the setter yourself or synthesize its definition (e.g. by declaring the property readwrite in your class continuation).

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



should not coordinate have self before it? (e.g., self.coordinate = c).

不应该协调之前有自我吗?(例如,self.coordinate = c)。

No, it should not. Use direct access in a partially constructed state, such as an initializer or -dealloc.

不,不应该。在部分构造的状态下使用直接访问,例如初始化程序或-dealloc.

Given the properties:

鉴于属性:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy, readwrite) NSString * title;

Your initializer should take the form:

您的初始化程序应采用以下形式:

- (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

回答by Alex Gray

I've seen tricky people do this....

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

Source.h

Source.h

@property (readonly) BOOL  isRunning;

Source.m

Source.m

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

There is very little documentation that I can find about these types of accessors... I'm pretty sure it is just a standard C construct... one which I am not very familiar... But this is a way to go if your mastery of the subject.. is better than mine...

关于这些类型的访问器,我能找到的文档很少……我很确定它只是一个标准的 C 构造……一个我不太熟悉的……但这是一种方法,如果你对这门学科的掌握……比我的好……