У меня есть вопрос по поводу следующего кода:слоя CALayer не autoreleased
@interface ViewController()
@property (nonatomic, weak) CALayer *someLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.someLayer = [CALayer layer];
self.someLayer.frame = CGRectMake(10.0, 10.0, 100.0, 100.0);
self.someLayer.backgroundColor = [UIColor yellowColor].CGColor;
[self.view.layer addSublayer:self.someLayer];
}
@end
Из моего понимания [CALayer layer]
должен возвращать autoreleased значения, которое должно жить так долго, как вызов метода в процессе. Затем он ссылается на слабое свойство someLayer
. Поскольку слой позже удерживается на уровне представления, все должно быть хорошо, и слой должен появиться. Что он делает, но только на устройствах < iPhone 5S. По крайней мере, когда я запускаю код в симуляторах.
На новых устройствах слой не будет отображаться. Изменение атрибута свойства для сильной решает проблему, но я хотел бы знать, почему слой сразу освобождается.
Есть ли у вас какие-либо намеки, как я могу отладить это поведение, чтобы увидеть, что изменилось?
Спасибо!
Update:
Использование self.someLayer = [CALayer [alloc]] init]
дает соответствующее предупреждение
, который я понимаю, потому что при использовании alloc
значение принадлежит абоненту. Так как владелец не сохраняет значение, нет никакой надежной ссылки. Инициализатор удобства, такой как layer
, должен автоматически сохранять сохраненное значение, которое должно быть доступно до тех пор, пока пул авторекламы не будет слит. В этом случае также нет предупреждений Xcode.
Update # 2: Он получает более интересным ... я тестировал код на iPhone 6 с прошивкой 8 и на iPhone 4 с прошивкой 6. слой не будет отображаться на ни их ...
НО
если установить точку останова в линии создания и шага над ним слой будет виден на тренажерах < iPhone 5S и на устройствах.
Как я могу проверить, что происходит под капотом?
Update # 3 и еще некоторые объяснения:
Существует большая статья на Большой Nerd Ranch об этом поведении ARC Gotcha - Unexpectedly Short Lifetimes
Взгляд на разборку для кода выше показывает, как ARC вставляет _objc_retainAutoreleasedReturnValue
Из статьи:
вы можете увидеть д'Арк «избежать тыс e autoorelease pool ": если метод возвращает объект с автореализацией, и вызывающему абоненту в противном случае не нужно висеть на нем, ARC может избежать поездки в пул автозапуска.Метод вернет сохраненный объект, и objc_retainAutoreleasedReturnValue избавится от него.
Таким образом, чтобы избежать проблемы, объявите сильное свойство (как я уже упоминал выше) или взглянем на ответ @ graver.
ARC включен? Это странно, возможно, вам нужно отлаживать устройство. Я не доверяю симуляторам. –
Да, ARC включен. – marcusficner