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)
奥列格的答案是正确的,但值得深入研究.您正在查看此接口定义:
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)
superview属性不一定是强属性,可以是其他私有弱属性的计算属性.
addSubview方法建立了从superview到子视图的强引用,而不一定是从子视图到superview.
在viewDidLoad方法结束时,view1不在视图hirarchy中,并且没有任何指向view1的其他对象,因此它被取消分配,但view2也有视图控制器指向它,因此view2不会被释放.
| 归档时间: |
|
| 查看次数: |
830 次 |
| 最近记录: |