2016-12-14 18 views
0

Состояния заголовка UIView, что SuperView свойства сильноЯвляется ли свойство UIView superview слабым или сильным?

open var superview: UIView? { get } 

Но он ведет себя так же, как слабое свойство, т.е. если я создаю view1 и view2, а затем вызвать view1.addSubview (VIEW2), а затем сохранить сильный реф to view2 only (not to view1), view1 будет деинсталлирован, хотя view2 ссылается на него через свой объект superview.

Итак, интересно, как это реализовано на самом деле.

Edit: например, этот код печатает «Deinit» (экземпляр ViewController отображается на экране), что означает, что view1 является deinited, хотя 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

Я не могу воспроизвести поведение. Можете ли вы опубликовать минимальный тестовый код? – shallowThought

ответ

5

Ответ Олега правилен, но его нужно вникать в это дальше. Вы изучаете это определение интерфейса:

open var superview: UIView? { get } 

, и вы предполагаете, что это сильное свойство. Он вообще этого не говорит. Он говорит, что UIView имеет свойство readonly superview. Нет сеттера, поэтому вы не ожидаете каких-либо аннотаций управления памятью (strong/weak/unowned).

Даже если он был сеттер, например, UIView.backgroundColor:

var backgroundColor: UIColor? { get set } 

Это говорит нам ровно ничего об управлении памятью. Нет никакого обещания, что этот UIColor будет сохранен в представлении. Он может свободно создавать свою собственную копию. Это бесплатная информация об извлечении из UIColor и генерация другого объекта для его внутреннего использования (например, CGColor) и выбросить его. Нет никакого обещания, что backgroundColor имеет поддержку ivar. Это бесплатно, чтобы быть вычисленным установщиком.

Некоторые свойства, как делегаты, отмечены 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, но на самом деле сохраняет свою ценность. Вы никогда не должны этого делать, но дело в том, что язык вас не останавливает.

Отвод от всего этого состоит в том, что, если вы заботитесь о том, чтобы объект продолжал существовать, вы несете ответственность за его сильную ссылку на него. Когда вам все равно, существует ли она, вы должны отпустить свою сильную ссылку на нее. Вам следует избегать полагаться на какой-то другой объект, чтобы поддерживать его для вас.

(На практике существует множество реальных случаев, когда невероятно удобно полагаться на то, что какой-то другой объект будет держать что-то для вас. Например, мы, конечно, полагаемся на то, что массивы содержат сильные ссылки на их содержимое, но вам нужно убедиться, что контейнер обещает такое поведение, если вам это нужно. Оглядываться на интерфейс недостаточно.)

К конкретному вопросу UIView, это вычисленное свойство. Хотя детали реализации, вот примерно как это реализовано в прошивкой 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; 
} 
+2

Это оставляет без ответа вопросы о том, как хранятся свойства делегата superlayer и layer ... Ответ заключается в том, что оба 'CALayerGetSuperlayer' и' CALayerGetDelegate' используют 'objc_read_weak', поэтому супервизор действительно является косвенным свойством с нулевым уровнем. –

+0

Имеет смысл, спасибо – timaktimak

+0

интересно видеть, что если слой имеет другой делегат, тогда метод superview ломается –

5

Свойство superview не обязательно является сильным имуществом и может быть вычисленным свойством другого частного слабого имущества.

Метод addSubview устанавливает сильную ссылку из супервизора в подвью и необязательно из подсмотра в супервизор.

К концу viewDidLoad метод view1 не находится в представлении hirarchy и не имеет других объектов, указывающих на view1, поэтому он освобождается, но view2 имеет также контроллер вида, указывающий на него, так что view2 не освобождается.

3

UIView состояние заголовочного SuperView свойство сильно

Он не утверждает, что на всех. В нем указано, что свойство is только для чтения. Вы не можете установить надзор, поэтому никаких проблем с политикой хранения не возникает. Вы даже не знаете, есть ли is «ссылка на просмотр». Все, что вы знаете, это то, что вы можете запросить супервизор с помощью синтаксиса свойств, и вам расскажут, что это такое. Как это делается за кулисами, не указывается, и вам это не нужно.

Сказав это: очевидно, что представление не имеет сильной ссылки на его супервизор, потому что если бы это было так, то был бы цикл сохранения (потому что супервизор владеет своим подсмотром и, следовательно, имеет сильную ссылку на него).