是否需要在UIViewController中声明UIButton属性作为UIKit中的强错误



我有一个相当基本的问题,我实际上不确定这是UIKit中的错误还是预期行为。

在应添加到视图控制器的subviews中并因此显示在屏幕上的UIViewController中声明视图属性时,似乎普遍同意这些属性应weak

weak声明背后的基本原理是有意义的,因为视图控制器已经通过其 subviews 属性拥有子视图,因此另一个强引用不会在此处添加任何值。这在许多 Stackoverflow 帖子中也得到了证实,例如这个。

我现在遇到了UIButton的问题.当我想以编程方式添加一个按钮并首先将其声明为UIViewController的属性然后调用[self.view addSubview:self.someButton]时,该按钮仅在声明为 strong 时显示,但在声明为 weak 时不会显示。

这是理解我的问题的最小示例代码:

@interface ButtonTestViewController ()
// only works with strong! 
// when declared weak, no button appears on the screen and the
// logging output doesn't contain the button as a subview...
@property (nonatomic, strong) UIButton *someButton;
@end
@implementation ButtonTestViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.someButton setCenter:self.view.center];
    [self.view addSubview:self.someButton];
    NSLog(@"subviews: %@", self.view.subviews);
}
- (UIButton *)someButton
{
    if (!_someButton) {
        UIButton *someButton = [UIButton buttonWithType:UIButtonTypeSystem];
        CGRect someButtonFrame = CGRectMake(0.0, 0.0, 100.0, 44.0);
        someButton.frame = someButtonFrame;
        [someButton setTitle:@"Do something" forState:UIControlStateNormal];
        [someButton addTarget:self action:@selector(someButtonPressed) forControlEvents:UIControlEventTouchUpInside];
        _someButton = someButton;
    }
    return _someButton;
}
- (void)someButtonPressed
{
    NSLog(@"button pressed...");
}
@end

我还设置了一个小要点,其中我还在UIButton旁边添加了另一个 UI 元素(UITextField(进行比较。当被声明为weak时,也会显示UITextField。那么,这是UIKit中的一个错误,还是实际上有原因不能weak声明UIButton

出口被创建为弱的事实主要有两个原因:

  • 没有必要将它们创建为strong因为它们已经由他们的超级视图拥有
  • 曾几何时,有一种常见的用途是将它们归零 - viewDidUnload避免在内存警告后创建僵尸,现在您可以免费获得它。如果视图消失了,你已经把它们放在零了

Reatain循环不是以这种方式创建的,它是一个对象A保留B,保留A创建一个保留循环,按钮本身不保留任何人。
您的问题是由于这样一个事实,即如果您将按钮实例直接添加到弱变量中,则在将其添加到保留所有权的人之前,它将立即释放。
您可以将按钮创建为weak但应以其他方式添加值:

  • 创建简单的局部变量,例如UIButton *someButton = [UIButton whatever]
  • 将其作为子视图添加到视图中
  • 现在,您可以安全地将引用传递给weak变量,因为按钮归视图所有
不使用

界面生成器时,不能使子视图变弱。你必须在你的情况下使用强。否则,按钮在添加到视图之前会释放。

最新更新