ios - UIView superview 属性是弱还是强?

标签 ios xcode uiview uikit superview

UIView header 表明 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)
    }
}

最佳答案

Oleg 的回答是正确的,但值得进一步深入研究。您正在查看此接口(interface)定义:

open var superview: UIView? { get }

并且您假设这意味着这是一个强大的属性。它根本没有这么说。它说 UIView 有一个只读的 superview 属性。没有 setter ,因此您不会期望任何内存管理注释(强/弱/无主)。

即使它有一个 setter,例如 UIView.backgroundColor:

var backgroundColor: UIColor? { get set }

这完全没有告诉我们有关内存管理的任何信息。不保证此 UIColor 将被 View 保留。制作自己的副本是免费的。它可以从 UIColor 中免费提取信息并生成一些其他对象供其内部使用(如 CGColor),然后将其丢弃。没有 promise backgroundColor 有一个支持 ivar。这是一个免费的计算 setter 。

一些属性,比如委托(delegate),被标记为weak:

weak var transitioningDelegate: UIViewControllerTransitioningDelegate? { get set }

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

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

class MyClass {
    private var _myProp: AnotherClass?
    weak var myProp: AnotherClass? {
        get { return _myProp }
        set { _myProp = newValue }
    }
}

myProp 声称是 weak 但实际上确实保留了它的值(value)。你永远不应该这样做,但关键是语言不会阻止你。

从这一切中得出的结论是,如果您关心一个对象是否继续存在,那么您有责任维护对该对象的强引用。当你不关心它是否存在时,你应该释放你对它的强引用。您应该避免依赖某些其他对象来为您维护它。

(在实践中,有很多真实的案例,依赖于其他对象会为你保留一些东西这一事实非常方便。例如,我们当然严重依赖于数组持有对其的强引用这一事实内容。但是,如果您需要,则由您确定容器是否 promise 该行为。仅查看界面是不够的。)

针对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;
}

关于ios - UIView superview 属性是弱还是强?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41141665/

相关文章:

ios - iPad Pro 需要调整屏幕大小吗?

ios - 大多数时候 HTML 不会第一次加载

iphone - UIView 和 XIB 连接。正在显示吗?

iphone - iOS - CAKeyFrameAnimation - 不播放

ios - 无效的代码签名权利 - 特别是 key 'dns-proxy' 的值 'com.apple.developer.networking.networkextension'

android - react-native 包的原生部分可以独立运行和开发吗?

ios - NSURLConnection 错误代码 -1100

ios - UIView 中的 AVPlayer

ios - 保留 UIView 如何与 iOS 中的 ARC 一起使用?

iphone - 为什么我尝试在背景上显示图像会导致显示白色?