为什么不直接使用属性创建对象?

时间:2014-03-09 18:02:34

标签: ios objective-c

我正在研究UIPopover,在其中一个示例中,我发现Popover对象是 已创建但该对象已分配给Viewcontroller的属性。

UIPopoverController* aPopover = [[UIPopoverController alloc] initWithContentViewController:content];
self.popoverController = aPopover;

这种转让的优点是什么,以及没有直接将物品分配给物业的理由?

3 个答案:

答案 0 :(得分:5)

其中没有“优点”。说

self.popoverController = 
    [[UIPopoverController alloc]  initWithContentViewController:content];

绝对等同。

另一方面,使用临时变量(aPopover)没有任何问题,如示例所示。它只是一个名字(一个指针);没有明显的空间或时间浪费。此外,应避免重复说出self.popoverController (设置或获取其值),因为这是方法调用 - 您正在通过setter方法或getter方法(可以合成,可能有副作用,实际上需要一些额外的时间)。因此,当有很多配置需要完成时(例如),最好按照示例中的说明进行:

UIPopoverController* aPopover = 
    [[UIPopoverController alloc]  initWithContentViewController:content];
// lots of configuration here, using the local automatic variable aPopover...
// ...and then, only when it is all done, call the setter:
self.popoverController = aPopover;

答案 1 :(得分:1)

唯一的原因是你可能在某个地方的教程中读过这篇文章。作者为了初学者的可读性而这样做了。你绝对可以使用:

self.popoverController = [[UIPopoverController alloc] initWithContentViewController:content];

所有这些都取决于您对编程的熟悉程度以及您希望代码的可读性。

答案 2 :(得分:1)

我同意其他人的看法,在这种情况下,将popover控制器分配给局部变量,然后再将其分配给类属性,这在很大程度上是一种风格问题。但这只是因为你保持对该弹出控制器的strong引用。在其他情况下,您具有weak属性,其中此局部变量模式至关重要。


例如,假设我们有一堆控件,我们将以编程方式添加到视图控制器的视图中:

@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UILabel *usernameLabel;
@property (nonatomic, strong) UILabel *emailLabel;
// and more labels

如果要将这些添加到视图控制器的视图中,可以执行以下操作:

- (void)addSubviewsAtPoint:(CGPoint)location
{
    self.containerView = [[UIView alloc] initWithFrame:[self frameForContainer:location]];
    [self.view addSubview:self.containerView];

    self.usernameLabel = [[UILabel alloc] initWithFrame:[self frameForUsernameLabel]];
    [self.containerView addSubview:self.usernameLabel];
    self.usernameLabel.text = self.username;

    self.emailLabel = [[UILabel alloc] initWithFrame:[self frameForEmailLabel]];
    [self.containerView addSubview:self.emailLabel];
    self.emailLabel.text = self.email;

    // etc.
}

但这也意味着当您删除子视图时,您不仅需要从视图层次结构中删除容器视图,而且还必须记住nil所有这些子视图的所有属性:

- (void)removeSubviews
{
    [self.containerView removeFromSuperview];
    self.containerView = nil;
    self.emailLabel = nil;
    self.usernameLabel = nil;
    // etc.
}

这引入了一个维护问题,即每次通过addSubviewsAtPoint添加新控件时,您还必须记住将其添加到removeSubviews,否则您可能会挂在将控制器从屏幕上移除后控制井。

为了简化您的生活,您可以制作所有这些属性weak(直觉是它拥有这些子视图的视图,而不是视图控制器):

@property (nonatomic, weak) UIView *containerView;
@property (nonatomic, weak) UILabel *usernameLabel;
@property (nonatomic, weak) UILabel *emailLabel;
// etc.

但现在,使用ARC,您的addSubviewsAtPoint不再有效,因为当您将对象分配给weak属性时,如果没有其他强引用,它将立即变为{{1 }}:

nil

因此,相反,我们使用您问题的局部变量模式来确保在我们将控件添加到视图中时不会过早地释放控件:

self.containerView = [[UIView alloc] initWithFrame:[self frameForContainer:location]];
[self.view addSubview:self.containerView];    // FAIL!!! self.containerView will be nil!

因此,因为我们正在使用弱属性,所以删除这些子视图现在变得更加简单,因为当我们删除{{1}时,我们不需要- (void)addSubviewsAtPoint:(CGPoint)location { UIView *containerView = [[UIView alloc] initWithFrame:[self frameForContainer:location]]; [self.view addSubview:containerView]; self.containerView = containerView; UILabel *usernameLabel = [[UILabel alloc] initWithFrame:[self frameForUsernameLabel]]; [containerView addSubview:usernameLabel]; usernameLabel.text = self.username; self.usernameLabel = usernameLabel; UILabel *emailLabel = [[UILabel alloc] initWithFrame:[self frameForEmailLabel]]; [containerView addSubview:emailLabel]; emailLabel.text = self.email; self.emailLabel = emailLabel; // etc. } 所有这些属性从我们的视图控制器的视图:

nil