我已经习惯使用弱和强引用以及何时使用它们,何时不使用它们,我得到了如下所述的案例(请查看有关该案例的评论警告)
@interface MPIViewController ()
@property (weak, nonatomic) UIView *subview;
@property (weak, nonatomic) UILabel *label;
@end
@implementation MPIViewController
// ...
// some code here
// ...
- (void)viewDidLoad
{
[super viewDidLoad];
self.subview = [[UIView alloc] init]; // warning here: assigning retained object to weak property
self.label = [[UILabel alloc] init]; // no warnings
[self.view addSubView: self.subview];
[self.view addSubView: self.label];
}
// ...
// some code here
// ...
@end
来自 - (void)addSubview:(UIView *)view
的说明:
此方法建立了一个强大的引用来查看和设置它的下一个 响应接收器,这是它的新超视图。
这意味着在方法完成后此对象不会是deallocated
,因为superview
将保留它并保留对它的强引用,因此该视图将保留在内存中,只要它的超级视图就在那里。我在这儿吗?
如果我理解正确分配,我也不确定。警告说在分配后它将是deallocated
,但这听起来不对,因为它不可能将任何变量分配给弱指针,因为它会在下一行代码中得到deallocated
?
对于UILabel
相同的分配工作正常,但对于UIView
则不然?编译器是否以某种方式对待UIView?这真让我感到困惑。
只需将UIView分配给本地方法变量,然后将其传递给setter,就可以轻松修复此代码:
UIView *tmpView = [[UIView alloc] init];
self.subview = tmpView;
方法中声明的变量默认为 strong
,因此具有这样的结构会删除警告,因为编译器认为此变量具有强引用,因此弱引用随后被分配给只要方法变量指向它,它就会被保留。但!这有什么意义,因为tmpView只是一个局部方法变量,并且在方法完成后会被转储?
答案 0 :(得分:2)
对第一个问题:
让我们仔细看看:
self.subview = [[UIView alloc] init];
[UIView alloc]
返回拥有+1的实例。这被分配给(不可见)强引用,该引用构建self
-init
。 -init
通过所有权。 (这是不正确的,如果-init
返回的实例不是原始接收者,但对于您的情况,这是足够的细节。)因此,我们可以将-init
的返回值视为所有权转移也是。
您将此实例分配给弱变量。在这一刻,可以被释放。 (阅读:ARC不承诺立即执行,IIRC。)在超级视图保持对象之前,实例变量可以是nil
。所以这段代码很危险:
self.subview = [[UIView alloc] init];
// _subview can be nil'ed
[self.view addSubView: self.subview]; // add nil
我不相信这是你的问题,但它可能是一个问题。 - 再想一想,是你的问题。最后阅读编辑。 - 要摆脱它,只需使用一个强大的局部变量:
UIView *subview = [[UIView alloc] init]; // defaults to __strong
[self.view addSubView: subview]; // adds an ownership
self.subview = subview;
第二个问题:
我不知道,为什么编译器在第二种情况下没有给出警告。如果您修复第一个案例,会发生什么?
在运行时,可能会对这两种情况进行不同的处理,因为在第一个实例发布时它是未定义的。也许作为优化的一部分,指针被重用。更详细:
__strong id completlyHiddenCompilerGeneratedVar;
… = [(completlyHiddenCompilerGeneratedVar=[UIView alloc]) init];
… = [(completlyHiddenCompilerGeneratedVar=[UILabel alloc]) init];
第一个实例将在创建第二个实例时被释放,因为它会覆盖内部强引用。
再次:修复第一个案例并告诉我们,第二个案例会发生什么。
答案 1 :(得分:0)
一个对象至少需要一个指向它的强指针才能保存在内存中。
因此,当您将其分配给弱指针时,条件未得到满足。如果您确实需要访问这些视图,请设置您的媒体资源strong
。