UIView superview属性弱还是强?

tim*_*mak 2 xcode uikit uiview superview ios

UIView标头声明superview属性很强

open var superview: UIView? { get }
Run Code Online (Sandbox Code Playgroud)

但它的行为就像一个弱属性,即如果我创建view1和view2然后调用view1.addSubview(view2),然后只将一个强引用保存到view2(而不是view1),即使view2引用了view1,它也会被删除通过其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)
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 7

奥列格的答案是正确的,但值得深入研究.您正在查看此接口定义:

open var superview: UIView? { get }
Run Code Online (Sandbox Code Playgroud)

你假设这意味着这是一个强大的财产.它根本没有说.它说UIView有一个只读superview属性.没有setter,所以你不会指望任何内存管理注释(强/弱/无主).

即使它有一个二传手,例如UIView.backgroundColor:

var backgroundColor: UIColor? { get set }
Run Code Online (Sandbox Code Playgroud)

这告诉我们关于内存管理的确切内容.没有承诺UIColor视图会保留这一点.它可以自由制作自己的副本.它是免费的提取信息,UIColor并为其内部使用生成一些其他对象(如a CGColor),并抛弃它.没有承诺backgroundColor有一个支持ivar.这可以自由地作为计算机设定器.

某些属性(如委托)标记为weak:

weak var transitioningDelegate: UIViewControllerTransitioningDelegate? { get set }
Run Code Online (Sandbox Code Playgroud)

您通常可以相信这些不会保留传递的对象,但请记住这些是信息性的,而不是保证.考虑这完全合法(并且完全可怕)Swift:

class AnotherClass {
    deinit { print("deinit") }
}

class MyClass {
    private var _myProp: AnotherClass?
    weak var myProp: AnotherClass? {
        get { return _myProp }
        set { _myProp = newValue }
    }
}
Run Code Online (Sandbox Code Playgroud)

myProp声称weak实际上确实保留了它的价值.你永远不应该这样做,但重点是语言并不能阻止你.

所有这一切的消失是,如果你关心一个物体继续存在,你有责任保持一个强有力的参考.当你不在乎它是否存在时,你应该释放你对它的强烈引用.您应该避免依赖其他对象来为您维护它.

(在实践中,有很多真实的案例,依赖于其他一些对象会为你提供一些东西这一事实非常方便.例如,我们当然很大程度上依赖于Arrays对其内容有强烈引用的事实.但是如果你需要它,你可以确定容器是否承诺这种行为.查看界面是不够的.)

对于具体问题UIView,这是一个计算属性.虽然是一个实现细节,但这里大致是它在iOS 10.1中的实现方式:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这没有回答关于如何存储超级层和层委托属性的问题......答案是"CALayerGetSuperlayer"和"CALayerGetDelegate"都使用`objc_read_weak`,因此superview确实间接地是一个归零弱属性. (2认同)

Ole*_*man 6

superview属性不一定是强属性,可以是其他私有弱属性的计算属性.

addSubview方法建立了从superview到子视图的强引用,而不一定是从子视图到superview.

在viewDidLoad方法结束时,view1不在视图hirarchy中,并且没有任何指向view1的其他对象,因此它被取消分配,但view2也有视图控制器指向它,因此view2不会被释放.