【问题标题】:iOS ARC @property and selfiOS ARC @property 和 self
【发布时间】:2013-08-21 08:37:08
【问题描述】:

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

在.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 代码是 Apple LLVM 4.1,这个问题导致 MRC 应用程序崩溃,:)

【问题讨论】:

  • @Puneeet 问题是该属性返回一个nil 指针,而实例变量已被初始化。
  • 坦率地说,我不明白反对意见。这是一个学习 Objective-C 的人提出的一个合理的问题,而且它也很清楚并且写得很好。

标签: ios properties automatic-ref-counting


【解决方案1】:

如果您仔细观察,您会发现编译器发出的警告说:

自动合成属性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

在您的实现文件中,但您将没有任何好处,而且您还将打破实例变量的命名约定。

【讨论】:

  • Gabriele 在 MRC 中我曾经这样编码,如果变量没有被其他类使用或分配,我不添加属性以避免保留 self.tV = [[uiview alloc] init ];现在似乎有点错误,如果使用 systhesis ctView,它不会创建 var _ctView,这很顺利。非常感谢,你拯救了我的一天
  • 我不确定我是否理解这个问题。你到底想避免什么?
  • @nickyu,不客气。另请记住,如果您不想保留分配,您可以将属性声明为weak。作为一般提示,尽可能使用属性。我想自从我宣布我的最后一个变量以来已经有好几年了;)
  • @nickyu 既然你是 SO 新手,让我借此机会提醒你,接受答案是一个好习惯 :)
【解决方案2】:

使用新的 Xcode,您不再需要声明 ivar,它会自动创建一个与属性同名但前缀为 _ 的 ivar。 因此,您的属性 ctView 的 ivar 称为 _ctView

如果你想使用自己的 ivar,你必须告诉编译器:

@synthesize ctView = ctView;

【讨论】:

  • 我认为@synthesize ctView; 就足够了;)
  • @GabrielePetronella 你可能是对的,但这样你肯定知道。
  • 是的,但它是无用的(而且不是那么漂亮)的代码 :) 试一试,你会发现 = ctView 是隐含的。
【解决方案3】:

如果你没有提供你自己的属性的 getter 和 setter 的实现,或者你只是 @synthesize 它们而不提供变量名,Objective-C 将自动通过一个名称等于 _ + property 的变量来支持你的属性姓名。因此,在您的情况下,您的 ctView 属性会自动由名为 _ctView 的变量支持。您自己定义的实例变量是一个不同的变量。

您可以通过 3 种方式修复它:

  1. 仅使用 getter 和 setter 来访问您的属性,因此请使用 self.ctView = [[CTView alloc] init... 而不是 ctView = ... 并删除您自己定义的变量。
  2. 使用正确的名称访问您的实例变量:_ctView = ...
  3. 在您的 .m 文件中使用 @synthesize ctView = ctView; 让编译器知道要使用哪个支持变量。

【讨论】:

    【解决方案4】:

    Xcode4.4以后不需要@synthesize一个带有实例变量的属性,可以自动完成。但是自动生成的ivar的名字是属性的前缀“_”,所以你ctViewiVar和self.ctView是不一样的,只是你手动添加了一个@sythesize ctView=ctView

    【讨论】:

    • 与上面的注释相同,@synthesize ctView; 就足够了,因为如果您不指定任何名称,= ctView 是隐含的。
    【解决方案5】:

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

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

    【讨论】:

    • -1 self.ctView不是名为 _ctView 的 ivar。 self.ctView 是一个方法调用。
    • 我在这里发现了一个有趣的地方。 :)
    猜你喜欢
    • 2012-04-19
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    相关资源
    最近更新 更多