Достигнуто освобождение UIPopovercontroller, пока всплывающее окно все еще отображается

111

Уверяю вас, что я искал ответ в SO на свой вопрос, но ни один из них не помог. Вот простой код, который должен UIImagePickerControllerсодержать UIPopoverController:

-(void)takePicture:(id)sender{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing=YES;
UIPopoverController *poc=[[UIPopoverController alloc] 
                            initWithContentViewController:picker];
[poc presentPopoverFromBarButtonItem:bbItem 
            permittedArrowDirections:UIPopoverArrowDirectionAny
                            animated:NO];
}

Теперь даже с первого раза до меня [UIPopoveController dealloc]добрались, пока ... ошибка и программа вылетает. Я не занимаюсь сохранением, выпуском или автоматическим выпуском в соответствии с ARC. Есть ли какие-то особые соображения UIPopoverControllersпри использовании ARC?

Микаил Абдуллаев
источник

Ответы:

203

UIPopoverControllers всегда следует хранить в переменной экземпляра. Хорошая практика - создать для него сильную собственность.

ОБНОВИТЬ:

Начиная с iOS 8 вы должны использовать UIPopoverPresentationController. Тогда вам не нужно сохранять ссылку на всплывающее окно, потому что оно управляется контроллером представления.

Пример кода (работает как на iPhone, так и на iPad):

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popoverPC = picker.popoverPresentationController;
popoverPC.barButtonItem = bbItem;
popoverPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:picker animated:YES completion:nil];
Феликс
источник
1
О, я вижу. Но разве это не похоже на UIAlertView? У меня никогда не было ivar для этого, я просто размещаю его там, где мне нужно, показываю его и затем [обычно] отпускаю. Чем отличается popovercontroller?
Микаил Абдуллаев
17
@Mikayil alertView сохраняется своим супервизором (как и все представления), но popoverController не является представлением, поэтому не имеет супервизора, поэтому не будет сохранен никем, если вы его не сохраните (или сохранить его в сильной переменной, имеющей более длинную область видимости, чем текущий метод - например, iVar).
fzwo
1
Но меня все еще смущает счетчик удержания UIPopoverController. Потому что я ставлю проверку перед тем, как выделить и запустить ее. И только если ноль, я выделяю новый. Но после того, как я выделил его в первый раз, я так и не получил ноль. То есть я вызываю метод один раз. Там я размещаю и инициализирую свой ivar. И в следующий раз, когда я снова вызываю этот метод, на этот раз я обнаруживаю, что мой ivar уже выделен. Если ARC позаботится об этом, тогда когда он это сделает. Или он самовыпускается?
Микаил Абдуллаев
@Mikayil ivars выпускаются ARC, когда объект освобождается или когда вы устанавливаете их на ноль
Феликс
но они не упоминают об этом в документации, в разделе « Как использовать » они используют локальную переменную
Амит Баттан
11

Когда функция завершается, других ссылок на контроллер всплывающего окна нет, поэтому он освобождается слишком рано.

Попробуйте вместо этого добавить его как члена вашего класса.

Тим

tarmes
источник
Разве я не должен сначала увидеть его, прежде чем он будет освобожден?
Микаил Абдуллаев
10

Добавляя то, что ответил @ phix23, создайте свойство * poc следующим образом:

@property (nonatomic, retain) IBOutlet UIPopoverController *poc;

а затем изменить

UIPopoverController *poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];

для

self.poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];
Orafaelreis
источник
11
Вам не обязательно помещать его в свой .h файл. Это сделает его общедоступным, и если вы этого не хотите, просто сделайте его свойством в своем файле .m.
Joshua Dance