Достигнуто освобождение 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

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

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

Тим


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

10

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

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

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

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

для

self.poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];

11
Вам не обязательно помещать его в свой .h файл. Это сделает его общедоступным, и если вы этого не хотите, просто сделайте его свойством в своем файле .m.
— Joshua Dance
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.