Приложение iPad аварийно завершает работу при изменении ориентации

Я разрабатываю приложение для iPad. Я разрешаю как альбомный, так и портретный режим. Мой пользовательский интерфейс в порядке в портретном режиме, но когда я меняю его на альбомный режим, мой пользовательский интерфейс портится. Я видел несколько сообщений SO, связанных с этим, и добавил следующий код в initWith ... в свой UIView.

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(abc)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];

После этого мой пользовательский интерфейс работает нормально в портретном режиме. Когда я перехожу в альбомный режим, с моим интерфейсом все в порядке. Но после того, как я вернул его в портретный режим, мое приложение вылетело. Я прочитал несколько сообщений о SO, связанных с сбоями приложений, и узнал об инструментах. Я включил зомби и обнаружил, что сообщение отправляется уже выпущенному объекту, и это сообщение поступает из NSNotificationCenter.

Есть ли что-то еще, что мне нужно сделать, кроме регистрации моего устройства? Кроме того, есть ли способ, где я могу изменить реализацию с UIView на UIViewController и реализовать методы, которые UIViewController имеет в отношении ориентации устройства? Пожалуйста, дайте мне знать, что мне нужно сделать, чтобы это сделать. Спасибо!


person user1982519    schedule 14.02.2013    source источник
comment
Выложите, пожалуйста, трассировку стека.   -  person trojanfoe    schedule 14.02.2013
comment
Я не могу опубликовать изображение, потому что моя репутация ниже 10.   -  person user1982519    schedule 14.02.2013
comment
Я не хочу изображения; текст будет в порядке (он должен появиться в панели отладчика).   -  person trojanfoe    schedule 14.02.2013
comment
Я обновил трассировку стека. Пожалуйста, взгляните на это.   -  person user1982519    schedule 14.02.2013


Ответы (2)


Где вы регистрируетесь для получения уведомлений? Вам необходимо удалить наблюдателя, когда вы собираетесь изменить ориентацию (либо в prepareForSegue, либо в willAnimateRotationToInterfaceOrientation, в зависимости от того, какие у вас настройки), чтобы предотвратить отправку сообщений о более недействительном объекте. Вы также не хотите нагромождать несколько уведомлений, если вы регистрируетесь в viewDidAppear / viewWillAppear.

Удалите наблюдателя, используя:

[[NSNotificationCenter defaultCenter] removeObserver:self];//removes all notifications for that object (the way I've used it before)

или, если хотите уточнить, сделайте что-нибудь вроде:

[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice];//remove just that notification
person Tommy Devoy    schedule 14.02.2013
comment
Я зарегистрировался для получения уведомлений в методе initWith ..., и у меня нет prepareForSeague, поскольку я не использую раскадровки, и у меня нет willAnimateRotationToInterfaceOrientation, потому что я реализую UIView, а не UIViewController. Куда мне удалить наблюдателя? - person user1982519; 14.02.2013
comment
Вы не встраиваете UIView в viewController? - person Tommy Devoy; 15.02.2013
comment
Нет. Я добавил этот код в метод dealloc, и теперь он работает нормально. Спасибо. - person user1982519; 15.02.2013

У класса UIViewController есть несколько методов, которые имеют дело с изменением ориентации. См. Документацию для обсуждения этих методов.

Один из методов, который вам следует изучить, - это viewWillLayoutSubviews. Это обычное место для выполнения макета вида вручную. Это вызывается каждый раз при изменении ориентации контроллера представления.

Эти методы используются гораздо чаще, чем регистрация для получения уведомлений об изменении ориентации устройства. Основываясь на ваших заявлениях о сбое, возможная проблема заключается в том, что вы никогда не удаляете добавленного вами наблюдателя. Для каждого вызова addObserver должен быть соответствующий вызов removeObserver. В противном случае вызывается наблюдатель, даже если он давно ушел. И это приводит к краху, который вы описываете.

person rmaddy    schedule 14.02.2013
comment
Прямо сейчас я реализую в UIView. Если в UIView нет другого способа справиться с этим, я планирую реализовать его в UIViewController. Но я почти уверен, что это можно реализовать в UIView с помощью подхода, которому я следовал. Я, должно быть, что-то упускаю. Есть ли другой способ реализовать то же самое в UIView? Попробую удалить Observer. - person user1982519; 14.02.2013