为什么这段代码来自iPhone开发者';什么是食谱?

为什么这段代码来自iPhone开发者';什么是食谱?,iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,我一直在试用Erica Sadun的书《iPhone开发者的食谱》中的一些视图代码,发现一些代码我不懂。以下是loadView方法的代码: - (void)loadView { // Create the main view UIView *contentView = [[UIView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame]]; contentView.backgrou

我一直在试用Erica Sadun的书《iPhone开发者的食谱》中的一些视图代码,发现一些代码我不懂。以下是loadView方法的代码:

- (void)loadView
{
    // Create the main view
    UIView *contentView = [[UIView alloc] initWithFrame: 
        [[UIScreen mainScreen] applicationFrame]];
    contentView.backgroundColor = [UIColor whiteColor];
    self.view = contentView;
   [contentView release];

    // Get the view bounds as our starting point
    CGRect apprect = [contentView bounds];

    // Add each inset subview
    UIView *subview = [[UIView alloc] 
        initWithFrame:CGRectInset(apprect, 32.0f, 32.0f)];
    subview.backgroundColor = [UIColor lightGrayColor];
    [contentView addSubview:subview];
    [subview release];
}

我的问题是,为什么她要发布contentView,但在
[contentView addSubview:subview]
中再次使用它?是否有
self.view=contentView
保留的contentView?

如果您这样声明您的属性 @属性(非原子,保留)。。。
然后是指定时保留该属性。如果你这样声明你的财产,那可能就是发生的事情 @属性(非原子,保留)。。。
然后是指定时保留该属性。如果您查看UIViewController的文档,就会发现view属性声明为:

@属性(非原子,保留)UIView*视图

这意味着,当您使用setView:方法(或使用=)左侧的.view时,将保留传入的任何值。因此,如果您通读代码并查看保留计数,您将得到以下结果:

- (void)loadView {
    // Create the main view
    UIView *contentView = [[UIView alloc] initWithFrame: 
            [[UIScreen mainScreen] applicationFrame]];  //retain count +1
    contentView.backgroundColor = [UIColor whiteColor];  //retain count +1
    self.view = contentView;  //retain count +2
    [contentView release];  //retain count +1

    // Get the view bounds as our starting point
    CGRect apprect = [contentView bounds];

    // Add each inset subview
    UIView *subview = [[UIView alloc] 
            initWithFrame:CGRectInset(apprect, 32.0f, 32.0f)];
    subview.backgroundColor = [UIColor lightGrayColor];
    [contentView addSubview:subview];
    [subview release];
}


我想说的是,真正有趣的是,在发布contentView之后,我们仍然可以向它发送消息,因为位于contentView指针末尾的对象仍然存在(因为它是通过调用setView:保留的)。

如果您查看UIViewController的文档,您将看到view属性声明为:

@属性(非原子,保留)UIView*视图

这意味着,当您使用setView:方法(或使用=)左侧的.view时,将保留传入的任何值。因此,如果您通读代码并查看保留计数,您将得到以下结果:

- (void)loadView {
    // Create the main view
    UIView *contentView = [[UIView alloc] initWithFrame: 
            [[UIScreen mainScreen] applicationFrame]];  //retain count +1
    contentView.backgroundColor = [UIColor whiteColor];  //retain count +1
    self.view = contentView;  //retain count +2
    [contentView release];  //retain count +1

    // Get the view bounds as our starting point
    CGRect apprect = [contentView bounds];

    // Add each inset subview
    UIView *subview = [[UIView alloc] 
            initWithFrame:CGRectInset(apprect, 32.0f, 32.0f)];
    subview.backgroundColor = [UIColor lightGrayColor];
    [contentView addSubview:subview];
    [subview release];
}


我想说,真正有趣的是,在发布contentView之后,我们仍然可以向它发送消息,因为位于contentView指针末尾的对象仍然存在(因为它是通过调用setView:保留的)。

这看起来是错误的
contentView
在方法结束之前不会发布,因此这可能不会导致任何问题,但我无法想象您为什么会故意以这种方式构建它。不是真的。对self.view的赋值保留了contentView,因此在创建对象时立即释放它是最接近的。它是故意这样构建的,因为(在Cocoa范例中)视图控制器保留视图是有意义的。这看起来是错误的
contentView
在方法结束之前不会发布,因此这可能不会导致任何问题,但我无法想象您为什么会故意以这种方式构建它。不是真的。对self.view的赋值保留了contentView,因此在创建对象时立即释放它是最接近的。它是故意以这种方式构建的,因为(在Cocoa范例中)视图控制器保留视图是有意义的。这是正确的,但我个人避免使用这种样式/模式——如果在某个时候您决定将该属性从
retain
更改为
assign
,那么该代码将自动开始崩溃。当然,UIViewController.view属性没有问题,但对于您自己的属性来说,这是自找麻烦的。是的,这正是它工作的原因,它是一种可怕的形式。一旦您发布了一个特定的引用,就不应该再使用它,它很容易出错。发布版应该移到最后,或者发布版之外的contentView的所有外观都应该更改为self.view。它实际上不符合样式的要求,除非“被认为有害”是一种样式。我不同意笼统地将其概括为可怕的形式。UIViewController是一个公共API,如果不中断依赖代码,属性属性就无法更改。这个习惯用法并不一定适用于所有情况,但它非常适合将视图控制器与其控制的视图耦合起来。此外,在赋值之后直接释放是最接近对象创建的。事实上,如果没有设置背景颜色的赋值,我可能会在对象创建周围包装一个自动释放,并将其直接分配给属性。如果它是自动释放的,那就好了,糟糕的形式是在lval被释放之后,在它被重新赋值之前,通过lval访问变量。在这种情况下,release和autorelease是完全不同的,因为autorelease在池耗尽之前不会使指向的数据无效。这是正确的,但我个人避免这种样式/模式——如果在某个时候您决定将该属性从
retain
更改为
assign
,然后该代码将自动开始崩溃。当然,UIViewController.view属性没有问题,但对于您自己的属性来说,这是自找麻烦的。是的,这正是它工作的原因,它是一种可怕的形式。一旦您发布了一个特定的引用,就不应该再使用它,它很容易出错。发布版应该移到最后,或者发布版之外的contentView的所有外观都应该更改为self.view。它实际上不符合样式的要求,除非“被认为有害”是一种样式。我不同意笼统地将其概括为可怕的形式。UIViewController是一个公共API,如果不中断依赖代码,属性属性就无法更改。这个习惯用法并不一定适用于所有情况,但它非常适合将视图控制器与其控制的视图耦合起来。此外,在赋值之后直接释放是最接近对象创建的。事实上,如果没有设置背景颜色的赋值,我可能会在对象创建周围包装一个自动释放,并将其直接分配给属性