2010-04-29 67 views
22

我试图创建一个只读属性。我想用创建该类实例的类中的值进行初始化,例如正在初始化只读属性

@property (retain,readonly) NSString *firstName;

我试着初始化它是这样的:

-(id)initWithName:(NSString *)n{ self.firstName = n; }

一旦我这样做,编译报道,只读属性不能分配错误。那我该怎么做呢?

回答

13

不要使用合成的二传:

firstName = [n retain]; //Or copy 

通常建议反正绕过任何init和dealloc的方法的制定者。

+0

我上面的实现的问题是,值不被保留。一旦我将保留添加到属性中,该赋值是否将该值设置为属性。如果其他对象访问此属性,此值将在那里。我也修改了我的问题 – awsome 2010-04-29 11:17:10

+0

为什么这会成为问题?使用'firstname = [n retain]'将使firstName成为'n'的指针。所以是的,当其他一些对象访问这个属性时,值就会在那里。 :) – Rengers 2010-04-29 11:39:49

+0

如果我尝试这样做,如果我访问此属性,我得到以下异常。程序收到信号:“EXC_BAD_ACCESS”。而这个错误不是由于任何其他财产。我在调试器中进行了很多调查。该属性显示“超出范围”。如果我分配它,self.firstName = n;。那么一切正常。 – awsome 2010-04-29 13:13:39

38

要么直接分配给实例变量(如果需要,不要忘记添加retaincopy),或者重新声明私有类扩展中的属性。就像这样:

在您的.h文件中:

@property (readonly, copy) NSString *firstName; 

在您.m文件:

@interface MyClass() 

// Redeclare property as readwrite 
@property (readwrite, copy) NSString *firstName; 

@end 


@implementation MyClass 

@synthesize firstName; 
... 

现在你可以使用合成的二传手在您的实现,但类的接口仍然显示财产只读。请注意,导入.h文件的其他类仍然可以调用-[MyClass setFirstName:],但它们不会知道它存在并将得到编译器警告。

+0

这看起来是一个很好的解决方法。谢谢。 – awsome 2010-04-29 11:30:03

+0

与使用@Renger建议的方法相比,使用合成的setter有什么优势? – Madbreaks 2012-12-19 20:23:23

2

您可以直接访问属性:

_firstName = n;

self.firstName = n意味着不会因为你@property (retain,readonly) NSString *firstName;指定readonly,因此编译器错误合成的setter方法。

+0

没有_firstName ... – 2016-04-06 10:56:07

+0

这是我的理解,_firstName将存在。这是在宣布财产时创建的基础伊娃。从Xcode 4.6开始,编译器应该自动为你创建。 – Bob9630 2016-05-05 16:36:25

+0

这就是我的理解@Bob9630。对于这个问题的其他答案在我的情况下没有产生期望的结果,虽然这样做。 – 2016-05-05 23:47:51