【问题标题】:Objective-C: Weak Pointer to a UITextField -> UITextField doesn't appearObjective-C:指向 UITextField 的弱指针-> UITextField 不出现
【发布时间】:2012-12-15 21:30:41
【问题描述】:

如标题中所述,我拥有UITextField 的属性。我将此UITextField 添加到UIView。

如果我有一个强指针,UITextField 就会出现,

如果我有一个弱指针,UITextField 不会出现。

当我有一个弱指针时出了什么问题?我对UIButton 做了同样的事情,然后它实际上出现了(带有强指针和弱指针)。

这里有一些代码:

CreateCategoryView.h

@interface CreateCategoryView : UIView 

@property (weak, nonatomic) UITextField *nameTextField;

@end

CreateCategoryView.m

@implementation CreateCategoryView

- (id)initWithFrame:(CGRect)frame andParent {
    self = [super initWithFrame:frame];
    if (self) {
        self.nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(5, 30, 310, 25)];
        self.nameTextField.borderStyle = UITextBorderStyleRoundedRect;
        self.nameTextField.textColor = [UIColor blackColor];
        self.nameTextField.backgroundColor = [UIColor whiteColor];
        [self addSubview:self.nameTextField];
    }
    return self;
}

@end

【问题讨论】:

  • 你能贴一些代码sn-ps吗?因为这里有几件事可能会出错。您需要将标签添加到视图中,以便视图获得所有权。也不会显示没有文字的标签...
  • 我将编辑我的问题。一秒
  • 顺便说一句:我没有提到这一点,但我正在以编程方式创建 UITextField,而不是使用 Interface Builder。
  • 您确定此代码有效吗?像 - (id)initWithFrame:(CGRect)frame andParent 这样的方法签名无法编译

标签: objective-c ios automatic-ref-counting


【解决方案1】:

您应该使用局部变量(默认为强变量)创建文本字段,然后将其分配给您的属性。无需对文本字段使用强引用,因为添加它的视图会保留强引用。

- (id)initWithFrame:(CGRect)frame  {
    self = [super initWithFrame:frame];
    if (self) {
        UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5, 30, 310, 25)];
        tf.borderStyle = UITextBorderStyleRoundedRect;
        tf.textColor = [UIColor blackColor];
        tf.backgroundColor = [UIColor whiteColor];
        _nameTextField = tf;
        [self addSubview:_nameTextField];
    }
    return self;
}

【讨论】:

  • @c2programming,看起来当您使用 buttonWithType 创建一个按钮时:它在向自身添加子视图时获得另一个保留,因此它的保留计数为 2,由于弱指针而减少一个,但还剩下一个可以让它活得足够长以被它的 superview 保留。
  • 注意:编译器可能会在最后一次使用的表达式之后立即释放tf,因此在添加子视图时_nameTextField可能仍然是nil。为了安全起见,请使用[self addSubview:tf] 而不是 [self addSubview:_nameTextField`。
【解决方案2】:

接受的答案是错误的。

问题是视图在创建后立即释放。您可以通过执行以下操作来看到这一点

__weak UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];

这样编译器会报错

warning: assigning retained object to weak variable; object will be released after assignment

您需要做的是有一个临时的strong 变量,正如@rdelmar 指出的,默认情况下是局部变量

所以

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];

相当于

__strong UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];

这将使视图保持足够长的时间以被调用addSubview的视图拥有

【讨论】:

    【解决方案3】:

    Apple document 有一个例子

    弱变量可能会造成混乱,尤其是在这样的代码中:

    NSObject * __weak someObject = [[NSObject alloc] init];

    在这个例子中,新分配的对象没有强引用,所以它立即被释放,并且 someObject 被设置为 nil。

    【讨论】:

      【解决方案4】:

      该对象没有被保留,因为它是一个弱指针,因此您的文本字段在初始化后立即被释放。使用弱属性指向强对象,以便对象保持保留。

      【讨论】:

      • 这不太合理。 -addSubview: 调用应该导致父视图保留文本字段。
      • 我用 UIButton(弱指针,然后将其添加到 UIView)和 UIButton 进行了相同的测试。所以肯定还有其他问题,对吧?
      • 这个答案不正确。文本字段实际上是在创建后立即释放的(因为弱引用),而不是在 init 方法的末尾。文本字段应该使用局部变量创建,然后分配给属性,如果你想使用弱引用,这应该没问题,因为它被添加到的视图将保持强引用。
      • @demosten 你的评论是错误的。 addSubview 实际上会保留子视图。这里的问题是该对象没有保持足够长的生命,甚至无法进行该调用。您可以通过创建一个局部变量 __weak UIView *view = [[UIView alloc] initWithFrame:f]; 并看到编译器抱怨 Assigning retained object to a weak variable; object will be released after assignment 来看到这一点
      • 是的,看来我错了。我会更深入地研究它,但 Paus.s 的评论是有道理的。有用的讨论。我会保留我的评论,以免破坏它。
      猜你喜欢
      • 2011-05-19
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-17
      相关资源
      最近更新 更多