2015-11-17 10 views
0

Я работаю над пользовательским интерфейсом приложения, и я делаю это программно. Я понимаю идею сохранения циклов и чувствую себя уверенно, что могу ее идентифицировать, но Xcode дает мне предупреждения, когда я пытаюсь избежать цикла сохранения.Управление памятью для пользовательского интерфейса

По существу, я создаю свойство под названием titleLabel, которое будет иметь мой заголовок, а в viewDidLoad Я инициализирую его и поместив на свой взгляд. Единственная проблема заключается в том, что я получаю предупреждение Xcode, которое говорит:

Назначение сохраненного объекта слабой переменной; объект будет освобожден после присвоения

Мое определение свойство выглядит следующим образом:

@property (nonatomic, weak) UILabel *titleLabel; 

Очевидно, что я мог бы исправить предупреждение Xcode путем изменения weak к strong в моем определении свойства, но я считаю, что было бы создать цикл сохранения (из моего понимания), потому что кнопка удерживается на контроллере просмотра, а контроллер просмотра удерживает кнопку.

Может ли кто-нибудь дать мне некоторое представление о том, как это сделать правильно?

+0

Это не будет сохранить цикл, потому что кнопка не имеет ссылку на контроллер представления, однако, если вы хотите сохранить свойство как 'weak' просто назначить использовать локальную переменную, если вы выделить и присвойте его свойству после того, как вы добавили его в свой вид. Локальная переменная будет содержать ссылку до тех пор, пока метод не выйдет, и представление будет содержать сильную ссылку позже. – Paulw11

ответ

1

Ваше понимание неверно. Если метка должна была содержать ссылку на контроллер своего вида, у вас будет цикл сохранения, если свойство было определено как strong. Однако представления не сохраняют ссылки на их контроллеры представлений, поэтому нет цикла. Xcode предупреждает вас о том, что после присвоения ссылка на ярлык исчезнет. Вы даже не спасены, добавив его в качестве подзаголовка (который сохранит его), потому что он уже выпущен к моменту попытки.

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

+0

Я не знаю, почему я предполагал, что мнения сохранят родительский VC.Итак, вы говорите, что мне не нужно беспокоиться о сохранении циклов, если мои ярлыки сильны, правильно? –

+1

Исправить. При определении свойств «IBOutlet», используемых для раскадровки или xibs, обычной практикой является определение их как «слабых». Это работает, потому что силовая загрузка гарантирует, что ссылка хранится где-то. Определение таких свойств, как 'strong', будет мешать очистке, поскольку механизм не имеет никакого способа повлиять на эту ссылку. – Avi

0

Я думаю, вы можете установить свойство на сильное, которое сохранит свою память, и когда ваше представление исчезнет, ​​вы можете установить этот объект на ноль, который выйдет из памяти.

+1

Вам не нужно использовать свойства nil для их выпуска. Если контроллер просмотра имеет только сильную ссылку, и он уходит, то последняя сильная ссылка уходит, и ARC автоматически освобождает память. Это половина цели ARC. – Avi

0

Когда вы создаете элемент пользовательского интерфейса и добавляете его как дочернее представление в родительский вид. В представлении «Родитель» содержится сильная ссылка на sub View. В вашем случае вы можете просто создать переменную UILabel внутри своей функции и добавить ее в родительский.

Тогда вы можете объявить слабое свойство, которое содержит ссылку на эту вновь созданную метку. Таким образом, родительский вид «владеет» меткой, и он заботится о том, чтобы очистить ярлык, когда родительский вид отключается.

@interface MasterViewController() 

@property (nonatomic,weak) UILabel * theLabel; 

@end 

@implementation MasterViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UILabel* myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
    [self.view addSubview:myLabel]; 
    self.theLabel = myLabel; 
}