2

这是我的情况:我有一个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

这样,我得到了我想要的:

  1. 屏幕上的 CustomViewClass 实例...
  2. ...只有一个所有者,它的超级视图...
  3. ...并且没有挥之不去的变量(customButtonLocal 在块结束后立即释放)。

但这不可能是做到这一点的“正确”方式。所以,最后,我的问题:

在不使用这种中间人解决方法的情况下,我应该如何分配和实例化这个以编程方式创建的变量?__weak

4

1 回答 1

2

CustomViewClass *customButton一个强有力的参考。

您通常为子视图声明变量的原因__weak IBOutlet是这些链接的存在并不意味着所有权。子视图归从 NIB/Storyboard 实例化的对象所有。你直接拥有那个对象,你也间接拥有它的依赖对象。

customButton是一个不同的故事:您以编程方式创建它,因此您的 NIB/Storyboard 不拥有它。因此,您应该引用它__strong(这是没有 ARC 修饰符时的默认值)。

于 2012-07-03T15:50:02.157 回答