iOS-ARC@property和self

iOS-ARC@property和self,ios,properties,automatic-ref-counting,Ios,Properties,Automatic Ref Counting,我刚开始用ARC编程, 当我用一个演示测试弱,强@属性时,我发现了一个奇怪的东西; 代码如下: 在.h文件中,我创建了一个成员变量ctView,并添加了@property来管理getter和setter @interface ViewController : UIViewController { CTView * ctView; } @property(nonatomic,strong)CTView * ctView; 然后在.m文件中,viewdi

我刚开始用ARC编程, 当我用一个演示测试
@属性
时,我发现了一个奇怪的东西; 代码如下:

在.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);
日志:


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

self.ctView
,这是一个名为
\u ctView
的iVar,永远不会得到alloc初始化。 只有
ctView
(注意!=
\ctView
)被alloc初始化


这就是为什么您无法获得
self.ctView
\u ctView
的地址

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

自动合成属性
ctView
将使用合成变量
\u ctView
,而不是现有变量
ctView

这是不言自明的

这是因为现代版本的编译器在声明属性时会自动合成变量。事实上,跳过
@syntheticed
指令将导致编译器以这种形式为您插入它

@synthesize ctView = _ctView;
自动创建

  • 实例变量
    \u ctView
  • getter方法
    -ctView
  • setter方法
    -setCtView:
声明变量不再需要该属性(除非您支持用Objective-C1.x编写的遗留代码),因此您可以跳过变量声明和
@synthesis
指令。如果你真的想使用你的变量,你必须显式地插入

@synthesize ctView; // in this case '= ctView' is implicit, so you can skip it

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

使用新的Xcode,您不再需要声明ivar,一个ivar将自动创建,其名称与属性相同,但前缀为
。 因此,属性
ctView
的ivar称为
\u ctView

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

@synthesize ctView = ctView;

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

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

  • 仅使用getter和setter访问属性,因此使用
    self.ctView=[[ctView alloc]init…
    而不是
    ctView=…
    并删除您自己定义的变量
  • 使用正确的名称访问实例变量:
    \u ctView=…
  • 通过在.m文件中使用
    @synthesis ctView=ctView;
    ,让编译器知道要使用哪个支持变量

  • 您不需要在Xcode4.4之后使用实例变量合成属性,它可以自动完成。但是自动生成的ivar名称是该属性的前缀,前缀为“\ux”,所以你
    ctView
    iVar和
    self.ctView
    不一样,只是你手动添加了一个
    @sythesize-ctView=ctView

    @puneet问题是属性返回了一个
    nil
    指针,而实例变量已经初始化。坦率地说,我不理解反对票。这是一个合理的问题从一个学习Objective-C的人那里,它也很清晰,写得很好。我认为
    @synthetic ctView;
    就足够了;)@GabrielePetronella你可能是对的,但这样你肯定知道。是的,但它没用(也不太漂亮)代码:)只要试一下,你就会发现
    =ctView
    是隐式的。-1
    self.ctView
    不是名为
    \ctView
    self.ctView
    的ivar。我在这里发现了一个有趣的地方。:)与上面相同的注释,
    @synthetic ctView;
    就足够了,因为
    =ctView
    是隐式的,如果你不指定任何name.Gabriele在MRC中我曾经这样编码,如果变量没有被其他类使用或赋值,我不会添加属性以避免通过self.tV=[[uiview alloc]init]保留;现在这似乎有点错误,如果使用systhesis ctView,它将不会创建var _ctView,这会很顺利。非常感谢,你节省了我的时间。我不确定我是否理解这个问题。你到底想避免什么?@nickyu,不客气。另外请记住,如果你不想在分配时保留,你可以将属性声明为
    。作为一般提示,尽可能使用属性。我想我已经有好几年没有声明上一个变量了;)@nickyu因为你是新来的,所以,让我借此机会提醒你,接受答案是一种很好的做法:)
    @synthesize ctView = ctView;