Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么一个弱引用被解除分配而另一个不';T_Ios_Objective C_Pointers_Weak References - Fatal编程技术网

Ios 为什么一个弱引用被解除分配而另一个不';T

Ios 为什么一个弱引用被解除分配而另一个不';T,ios,objective-c,pointers,weak-references,Ios,Objective C,Pointers,Weak References,我已经习惯于使用弱和强引用,以及何时使用和何时不使用它们,我遇到了如下所述的情况(检查有关警告的评论) 从-(void)addSubview:(UIView*)视图的描述中: 此方法建立视图的强引用并设置其下一个 接收器的应答器,这是它的新superview 这意味着该对象在方法完成后不会被解除分配,因为它的超级视图将保留它并保持对它的强引用,因此只要它的超级视图在内存中,该视图就会一直保留在内存中。我就在这里吗 我也不确定我是否正确理解这里的赋值。警告说它将在赋值后立即被解除分配,但这听起来是

我已经习惯于使用引用,以及何时使用和何时不使用它们,我遇到了如下所述的情况(检查有关警告的评论)

-(void)addSubview:(UIView*)视图的描述中

此方法建立视图的强引用并设置其下一个 接收器的应答器,这是它的新superview

这意味着该对象在方法完成后不会被解除分配,因为它的
超级视图将保留它并保持对它的强引用,因此只要它的超级视图在内存中,该视图就会一直保留在内存中。我就在这里吗

我也不确定我是否正确理解这里的赋值。警告说它将在赋值后立即被
解除分配
,但这听起来是错误的,因为这样就不可能将任何变量分配给弱指针,因为它将在下一行代码中被
解除分配

对于
UILabel
来说,相同的赋值可以正常工作,但是对于
UIView
来说就不行了?编译器对待UIView的方式是否有所不同?这真让我困惑,这怎么可能

只需将UIView分配给本地方法变量,然后将其传递给setter,即可轻松修复此代码,如下所示:

UIView *tmpView = [[UIView alloc] init];
self.subview = tmpView;

默认情况下,方法中声明的变量是
strong
,因此使用这种结构会删除警告,因为编译器认为该变量具有强引用,因此,只要方法变量指向该变量,就会保留随后分配给该变量的弱引用。但是tmpView只是一个局部方法变量,在方法完成后将被转储,这有什么意义呢?

一个对象至少需要一个指向它的强指针才能保存在内存中

因此,当您将其分配到弱指针时,该条件不被满足。如果确实需要访问这些视图,请将属性设置为强属性。

到第一个问题:

让我们仔细看看:

self.subview = [[UIView alloc] init];
[UIView alloc]
返回所有权为+1的实例。这被分配给一个(不可见)强引用,它构建
-init
self
-init
通过传递所有权。(这是不正确的,如果
-init
返回的实例不是原始接收者,但对于您的案例来说,这已经足够详细了。)因此,我们也可以将
-init
的返回值视为所有权转移

将此实例指定给弱变量。在这一刻,它可以被释放。(阅读:ARC不承诺立即执行,IIRC。)在对象被其superview持有之前,实例变量可以是
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];
当创建第二个实例时,第一个实例将被解除锁定,因为它覆盖了内部强引用


再次:修复第一个案例,并告诉我们第二个案例会发生什么。

如果您对获取警告的代码进行注释,您将看到警告也会出现在第二个alloc中。有人需要强烈引用视图。如果它们不是IB出口,则强指针通常由控制器持有。在这种情况下,您的视图应该是
strong
。他希望将视图作为子视图添加到视图中。视图保留其子视图。他们应该持有这些观点。这就是为什么他要问。此外,在一种情况下有一个警告,而在另一种情况下没有人。@Maciej Pigulski您的代码中有拼写错误吗?是不是应该是[…addSubview:*self.*subview]?@Amin Negm Awad,是的,这是一个拼写错误,我现在已经解决了。你对其他事情的看法也是对的。@ockulus不真实。没有弧线+alloc是所有权转移。它失去了所有权,因此返回的对象必须由强指针保存。否则你会马上失去目标。哎呀,今天早上我的脑子完全倒了。很抱歉,我以为我们在处理手动内存管理。事实上ARC可以立即释放一个“弱”引用是这样设计的吗?它到底有什么用途?因为也许我只是缺少了一个概念,这就是为什么我会感到困惑。这里的语言允许我将一个变量分配给一个弱属性,但这是我不应该做的事情(尽管它在某些情况下有效,我将在本评论的最后一部分讨论这个问题)。我已经用一个默认为强的局部变量做了一个变通(问题中提到,我知道这可以通过这种方式解决,还有另一个关于比特的问题也是令人困惑的——见问题的最后一段)。至于我应该修复其中一个警告的问题:生成此场景的代码比这里的示例要大得多。现在,我创建了一个示例视图控制器,希望重现此问题,我立即收到两个警告。此问题源于代码(它并不复杂,只是有更多的代码,但并不严重)我已经通过将UIView分配给局部变量解决了这个问题,警告消失了,但UILabel没有出现警告。正如前面提到的,这种情况下的处理是隐藏的,您决不能依赖它。但是我会
__strong id completlyHiddenCompilerGeneratedVar;
… = [(completlyHiddenCompilerGeneratedVar=[UIView alloc]) init];
… = [(completlyHiddenCompilerGeneratedVar=[UILabel alloc]) init];