这是我的情况:我有一个UIViewController
管理子视图层次结构的,可能如下所示:
此视图是从.xib
. 我希望能够保持对 topView 的每个子视图的访问——也就是说,我想要一个指向每个子视图的指针,这样我就可以说:
[button1 setText:@"Hello!"];
通常,要做到这一点,我会使用 Interface Builder 连接我想要访问的每个元素,从而生成一个看起来像这样的标题:
@interface MyViewController : UIViewController
{
__weak IBOutlet UIView *view;
__weak IBOutlet UILabel *label;
__weak IBOutlet UIButton *button1;
__weak IBOutlet UIButton *button2;
}
@end
这些实例变量是__weak
,这很好,因为当我的视图控制器“获取”它们时,它们已经由我的视图控制器的根视图拥有(令人困惑的是,我在快速图中将其标记为“topView”)。事实上,我希望这些引用是弱的——当我的根视图被释放时,它的所有子视图也应该被释放。伟大的。
但是假设我想创建一个新的 UI 元素,也许是一个自定义按钮,完全在代码中。我将调用这个元素CustomViewClass
,它将从UIView
. 我将创建的实例CustomViewClass
将被调用customButton
。与我的视图的其他子视图一样,我希望“访问”customButton
以便与它进行交互。然而,我知道,像任何其他子视图一样,customButton
它的父视图将拥有它,这就是它应该的样子——再次,我希望它在我的视图被释放时被释放。这让我觉得我应该将此视图声明__weak
为我的视图控制器的实例变量或属性。让我们这样做:
@interface MyViewController : UIViewController
{
__weak IBOutlet UIView *view;
__weak IBOutlet UILabel *label;
__weak IBOutlet UIButton *button1;
__weak IBOutlet UIButton *button2;
__weak CustomViewClass *customButton;
}
@end
然后,在我的实现中:
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
customButton = [[CustomViewClass alloc] init];
[[self view] addSubview:customButton];
}
@end
正如您可能已经意识到的那样,这不起作用,编译器将发出警告以启动。就像是:
Assigning retained object to weak variable; object
will be released after assignment
我目前用一些非常糟糕的风格来躲避这种警告:
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
CustomViewClass *customButtonLocal = [[CustomViewClass alloc] init];
[[self view] addSubview:customButtonLocal];
customButton = customButtonLocal;
}
@end
这样,我得到了我想要的:
- 屏幕上的 CustomViewClass 实例...
- ...只有一个所有者,它的超级视图...
- ...并且没有挥之不去的变量(customButtonLocal 在块结束后立即释放)。
但这不可能是做到这一点的“正确”方式。所以,最后,我的问题:
在不使用这种中间人解决方法的情况下,我应该如何分配和实例化这个以编程方式创建的变量?__weak