UIView标头声明superview属性很强
open var superview: UIView? { get }
但它的行为就像一个弱属性,即如果我创建view1和view2然后调用view1.addSubview(view2),然后只保存一个强引用到view2(而不是view1),view1将被删除,即使view2通过superview属性引用它。
所以,我想知道它是如何在现实中实施的。
编辑:例如,此代码打印“deinit”(ViewController实例显示在屏幕上),这意味着view1
已被删除,即使view2
应该通过superview
属性强烈保留它。
class View: UIView {
deinit {
print("deinit")
}
}
class ViewController: UIViewController {
var view2 = UIView()
override func viewDidLoad() {
super.viewDidLoad()
let view1 = View()
view1.addSubview(view2)
}
}
答案 0 :(得分:7)
Oleg的回答是正确的,但值得深入研究。您正在查看此接口定义:
UIView
而你假设这意味着这是一个强大的财产。它根本没有说。它说superview
具有只读UIView.backgroundColor
属性。没有setter,所以你不会指望任何内存管理注释(强/弱/无主)。
即使它有一个setter,例如var backgroundColor: UIColor? { get set }
:
UIColor
这告诉我们关于内存管理的一切。视图无法保留此UIColor
。它可以自由制作自己的副本。它是CGColor
中的免费提取信息,并为其内部使用生成一些其他对象(如backgroundColor
),并抛弃它。没有承诺weak
有一个支持ivar。这可以自由地成为计算机设定器。
某些属性(如委托)标记为weak var transitioningDelegate: UIViewControllerTransitioningDelegate? { get set }
:
class AnotherClass {
deinit { print("deinit") }
}
class MyClass {
private var _myProp: AnotherClass?
weak var myProp: AnotherClass? {
get { return _myProp }
set { _myProp = newValue }
}
}
您通常可以相信这些不会保留传递的对象,但请记住这些是信息,而不是保证。考虑这完全合法(并且完全可怕)Swift:
myProp
weak
声称是UIView
,但确实保留了其价值。你永远不应该这样做,但重点是语言不能阻止你。
所有这一切的消失是,如果你关心一个物体继续存在,你有责任保持对它的强烈引用。当你不在乎它是否存在时,你应该释放你对它的强烈引用。你应该避免依赖其他一些对象为你维护它。
(在实践中,有很多真实的案例,依赖于其他一些对象会为你提供一些东西这一事实非常方便。例如,我们当然很大程度上依赖于Arrays强烈引用它们的事实。但是,如果你需要它,你可以确定容器是否承诺这种行为。看看界面是不够的。)
对于- (UIView *)superview {
UIView *result;
if ([UIView _isAccessingModel] != 0x0) {
id visualState = [self visualState];
result = [visualState mSuperview];
}
else {
if ([self viewFlags] & 0x400000)) {
CALayer *superLayer = CALayerGetSuperlayer([self layer]);
result = nil;
if (superlayer != nil) {
result = CALayerGetDelegate(layer);
}
}
}
return result;
}
的具体问题,这是一个计算属性。虽然是一个实现细节,但这里大致是它在iOS 10.1中的实现方式:
{{1}}
答案 1 :(得分:6)
superview属性不一定是强属性,可以是其他私有弱属性的计算属性。
addSubview方法建立了从superview到子视图的强引用,而不一定是从子视图到superview。
在viewDidLoad方法结束时,view1不在视图hirarchy中,并且没有指向view1的任何其他对象,因此它被取消分配,但view2也有视图控制器指向它,因此view2不会被释放。
答案 2 :(得分:4)
UIView标头声明superview属性很强
根本没有说明。它声明的是属性是只读。您无法设置超级视图,因此甚至不会出现保留策略问题。您甚至不知道是 a"超级视图参考"。所有你知道的是,你可以通过属性语法要求superview,你会被告知它是什么。如何在幕后完成并没有指定,你也不应该关心它。
话虽如此:显然一个观点没有强烈引用它的超级视图,因为如果它确实存在,那么就会有一个保留周期(因为superview拥有它的子视图,因此对它有强烈的参考)。