我正在研究UIPopover
,在其中一个示例中,我发现Popover
对象是
已创建但该对象已分配给Viewcontroller
的属性。
UIPopoverController* aPopover = [[UIPopoverController alloc] initWithContentViewController:content];
self.popoverController = aPopover;
这种转让的优点是什么,以及没有直接将物品分配给物业的理由?
答案 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