viewDidAppear: дважды вызывается на контроллере модального представления, представленном при запуске - PullRequest
2 голосов
/ 06 марта 2009

Разрешение: При попытке воссоздать эту ошибку в новом проекте для отправки в Apple, я обнаружил, что он характерен для iPhone OS 2.1, и компиляция для 2.2 устраняет проблему. Стивен, спасибо за вашу помощь; Я приму ваш ответ, так как он сработал бы, если бы ошибка все еще существовала или я не хотел компилировать для 2.2.


У меня есть приложение, которое радикально меняет свою схему базы данных таким способом, который требует от меня преобразования записей старого стиля в записи нового стиля в коде. Так как пользователи могут хранить много данных в этом приложении, я пытаюсь отобразить контроллер модального представления с индикатором выполнения, в то время как он переносит данные (то есть, как первое, что видит пользователь). viewDidAppear: этого контроллера представления начинает транзакцию базы данных, а затем запускает фоновый поток для фактического переноса, который иногда использует performSelectorInMainThread:withObject:waitUntilDone:, чтобы сообщить потоку переднего плана обновить индикатор выполнения.

Проблема в том, что viewDidAppear: вызывается дважды. Я заметил это, потому что этот шаг «начать транзакцию» завершается неудачно с сообщением «база данных занята», но установка точки останова показывает, что он действительно вызывается два раза - один раз -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:], а затем -[UIViewController modalPresentTransitionDidComplete]. Эти имена, по-видимому, являются частными методами UIViewController, поэтому я предполагаю, что это либо ошибка в структуре, либо я делаю что-то, что UIKit не ожидает от меня.

Две соответствующие выдержки из кода (некоторые нерелевантные коды были обобщены):

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    (register some default settings in NSUserDefaults)

    // doing this early because trying to present a modal view controller 
    // before the view controller is visible seems to break it
    [window addSubview:[self.navigationController view]];

    // this is the method that may present the modal view
    [self.databaseController loadDatabaseWithViewController:self.navigationController];

    if(!self.databaseController.willUpgrade) {
        [self restoreNavigationControllerState];
    }
}

И из моего класса DatabaseController:

- (void)loadDatabaseWithViewController:(UIViewController*)viewController {
    (open the new database)

    (compute the path the old database would live at if it existed)

    if([[NSFileManager defaultManager] fileExistsAtPath:oldDBPath]) {
        (open the old database)

        [viewController presentModalViewController:self animated:NO];
    }
}

Итак, есть что-то, что я здесь напортачу, или я должен отправить отчет об ошибке в Apple?

1 Ответ

3 голосов
/ 06 марта 2009

Я тоже видел это в своем приложении. Я никогда не получал это полностью подтверждено, но я думаю, что это то, что происходит:

  1. Загрузить корневой вид
  2. Загрузить модальный вид
  3. ОС отправляет представление. Появилось уведомление для представления на шаге 1
  4. Текущий контроллер представления , который в данном случае является вашим классом DatabaseController, получает его
  5. ОС отправляет представление, появилось уведомление для модального представления
  6. Текущий контроллер представления получает уведомление. В этом случае это тот же контроллер, что и в прошлый раз

В моем случае я просто сбросил то, что произошло при первом вызове, на viewDidAppear:.

В вашем случае на ум приходят два варианта: статическая переменная для отслеживания того, начали ли вы уже обновление; или посмотрите параметр UIView*, переданный перед запуском.

...