ios - 是否需要在 UIViewController 中声明 UIButton 属性作为 UIKit 中的一个错误?

标签 ios objective-c memory-management uikit automatic-ref-counting

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

UIViewController 中声明 View 属性时,似乎普遍同意应该将其添加到 View Controller 的 subviews 中,从而显示在屏幕上,这些属性应该变得

这个 weak 声明背后的基本原理是有道理的,因为 View Controller 已经通过其 subviews 属性拥有 subview ,因此另一个强引用不会在此处添加任何值。许多 Stackoverflow 帖子也证实了这一点,例如this one .

我现在遇到了 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

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

最佳答案

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

  • 不需要将它们创建为 strong 因为它们已经被它们的父 View 拥有
  • 曾几何时,在 -viewDidUnload 中通常使用 nil 它们以避免在内存警告后创建僵尸,现在您可以免费获得它。如果 View 消失了,您已经拥有它们了

retain循环不是这样创建的,它是一个对象A保留B,retain A创建一个retain cycle,按钮本身没有保留。
你的问题是因为如果你直接将按钮实例添加到一个弱变量,在将它添加到保留所有权的人之前,它会立即被释放。
您可以将按钮创建为 weak,但您应该以另一种方式添加值:

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

关于ios - 是否需要在 UIViewController 中声明 UIButton 属性作为 UIKit 中的一个错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36495834/

相关文章:

c++ - 如何使用 "new"而不是 malloc 分配内存?

c++ - STL 容器中的内存释放

ios - 无法跨多个 iOS 设备同步 Amazon Cognito 数据集

ios - 大写字符在Iphone中转换为区分大小写

iphone - ASIHTTPRequest,EXC_BAD_ACCESS 当请求完成时

objective-c - 在 switch 语句中达到默认值后 EXC BAD ACCESS

c++ - 何时释放 unique_ptr?

ios - "This application is modifying the autolayout engine"错误(Swift iOS)

ios - 如何在 TabBar 应用程序中强制执行方向

ios - 有没有比使用 NSCoder 编码和解码所有内容更好的方法将自定义类保存到 NSUserDefaults?