7

in my projects I don't use Interface Builder and I've noticed one thing that I don't know how to explain. Yet. So, to the point. When we are using IB and defining elements of user interface like UILabel or UIButton in our controller we use this ugly prefix IBOutlet and a 'weak' modifier. This works like music. But when we decide not to use IB and define whole user interface from code it just doesn't work.

Let's assume that I want to add UILabel to controller (using IB). I will have something like this i *.h file:

@property (nonatomic, weak) IBOutlet UILabel * label;

And I don't have to do anything more in *.m file. But if I remove the *.xib file and try to setup my UILabel in, for example, one of init methods, like this:

self.label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,100,20)];
self.label.text = @"some text";
[self.view addSubview:self.label];

It doesn't work until I alter my *.h file to this:

@property (nonatomic, strong) UILabel * label;

Now, I know the difference between weak and strong but I have no idea why we can use weak for ui elements when using IB? Something must keep a strong pointers to these elements, right? But what?? In second case it is controller, but I don't understand how it behaves in the first case.

4

3 回答 3

5

Interface Builder 为 IBOutlets 创建弱引用的原因如下:

IB 知道视图由其父视图保留。因此,视图树中的任何对象都不需要强引用,除了根对象。view视图控制器在其主要属性中保留了这个强引用。

现在,当视图处于卸载状态时(至少在 iOS 5 之前),UIViewController 的view属性设置为 nil,释放主视图。如果该超级视图的子视图的 IBOutlets 是强引用,它们会将视图层次结构的一部分保留在内存中。这是不需要的(并且在访问这些孤立视图时可能会导致混淆)。

于 2013-02-07T22:10:34.370 回答
4

某些东西必须保持对这些元素的强指针,对吗?但是什么??

正确,您必须至少有 1 个对对象的强引用才能存在。您只需要对 UI 的根级别对象有一个强引用,低于此的任何内容都可能是弱引用(因为父对象将拥有它们的子对象)。.xib与其文件所有者协调的文件会为您完成此操作。

有关文件的工作原理,请参阅xib文档。具体来说,这个片段:

您通常需要对顶级对象的强引用以确保它们不会被释放;您不需要对图中较低的对象进行强引用,因为它们归其父对象所有,并且您应该尽量减少创建强引用循环的风险。

从实际的角度来看,在 iOS 和 OS X 中的 outlet 应该被定义为声明的属性。出口通常应该是弱的,除了从文件所有者到 nib 文件中的顶级对象(或者,在 iOS 中,故事板场景)应该是强的。因此,您创建的奥特莱斯通常应该很弱

于 2013-02-07T21:53:23.223 回答
1

尽管有公认的答案,但这就是您可以在代码中实现的方法

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,100,20)]; // strong ref
label.text = @"some text";
[self.view addSubview:label]; // strong ref from superview
self.label = label; // weak ref
// Now you can do `label = nil;`

这是从 XIB 加载时的要点。当它被分配给您的弱属性时,它label 已经具有超级视图。

于 2013-02-07T22:12:44.137 回答