2013-08-21 51 views
-2

我刚开始用ARC编程, 当我测试weakstrong@property用demo时,我发现一个奇怪的东西; 这里是代码:iOS ARC @property and self

在.h文件中,我创建了一个成员变量ctView并添加了@property来管理getter和setter。

@interface ViewController : UIViewController 
    { 
     CTView * ctView; 
    } 
    @property(nonatomic,strong)CTView * ctView; 

然后在.m文件中,viewdidload方法,我打印出点地址。

ctView = [[CTView alloc] initWithFrame:CGRectMake(10,10,300,400)];  
NSLog(@"%p %p ",self.ctView,ctView); 

登录:

0x0 0x7156530 

谢谢你们了,我犯了一个错误的是,MRC代码是在LLVM GCC 4.2编译器和ARC码是苹果LLVM 4.1,这个问题使得MRC应用程序崩溃,:)

+0

问题是什么? –

+0

@Puneeet问题是该属性返回一个'nil'指针,而实例变量已经初始化。 –

+1

我坦白地不明白downvotes。这是一个学习Objective-C的人的一个合理的问题,它也很清晰,写得很好。 –

回答

-1

self.ctView,这是一个名为_ctView的iVar,永远不会获得alloc inited。 只有ctView(注意!= _ctView)被分配inited。

这就是为什么你没有得到self.ctView_ctView的地址。

+0

-1'self.ctView'不是**名为'_ctView'的ivar。 'self.ctView'是一个方法调用。 –

+0

我在这里找到了一个有趣的地方。 :) – John

+0

这将意味着什么? –

2

如果你仔细观察,你会发现从编译器警告说:

Autosynthesized财产ctView将使用合成变量_ctView,不存在变量ctView

这是相当不言自明。

发生这种情况是因为现代版本的编译器会在声明属性时自动合成变量。事实上跳过@synthesized指令的问题会导致编译器以这种形式

@synthesize ctView = _ctView; 

自动创建

  • 实例变量_ctView
  • getter方法-ctView
  • 插入你
  • setter方法-setCtView:

声明变量该属性不再需要(除非您支持使用Objective-C 1.x编写的遗留代码),因此您可以跳过变量声明和@synthesize指令。如果你真的想用您的变量,你必须明确地插入

@synthesize ctView; // in this case '= ctView' is implicit, so you can skip it 
在实现文件

,但你不会有任何好处,你也将打破实例变量的命名约定。

+0

酷,很多thx朋友,这是一个非常好的解释。 – nickyu

+0

Gabriele在MRC中我用这样的代码,如果变量没有被其他类使用或分配,我不添加属性以避免保留self.tV = [[uiview alloc] init];现在看起来有点错误,如果使用sythesis ctView,它不会创建var _ctView,这可以顺利进行。非常感谢,你救了我的一天 – nickyu

+0

我不知道我理解这个问题。你想完全避免什么? –

1

随着新的Xcode你不再需要声明伊娃,一个会自动创建与该属性相同的名称,但前缀为_。 因此,您的财产ctView伊维尔被称为_ctView

如果你想使用自己的伊娃,你将不得不告诉编译器这样的:

@synthesize ctView = ctView; 
+0

我觉得'@synthesize ctView; '就够了;) –

+0

@GabrielePetronella你可能是对的,但这种方式你肯定知道。 – rckoenes

+0

是的,但它没用(而不是很漂亮)代码:)只要尝试,你会发现'= ctView'是隐含的。 –

1

如果你不提供自己的财产的getter和setter方法,或者如果你只是@synthesize他们如果没有提供变量名称,Objective-C将自动使用名称等于_ +属性名称的变量来备份您的属性。所以在你的情况下,你的ctView属性会自动支持一个名为_ctView的变量。您自己定义的实例变量是不同的变量。

您可以在3种方式解决这个问题:

  1. 只使用getter和setter方法来访问你的财产,所以使用self.ctView = [[CTView alloc] init...代替ctView = ...并删除你自己定义的变量。
  2. 使用正确的名称访问您的实例变量:_ctView = ...
  3. 通过在.m文件中使用@synthesize ctView = ctView;,让编译器知道使用哪个备份变量。
1

你不需要@synthesize在Xcode4.4之后有一个实例变量的属性,它可以自动完成。但是自动制作的伊娃的名字是该属性的前缀“_”,所以你ctView iVar和self.ctView是不一样的,除了你手动添加一个@sythesize ctView=ctView;

+0

与上面相同的注释,'@synthesize ctView;'就足够了,因为如果你没有指定任何名字,'= ctView'是隐含的。 –