2

解決策: Apple に提出する新しいプロジェクトでこのバグを再現しようとしているときに、これが iPhone OS 2.1 に固有のものであることを発見し、2.2 用にコンパイルすると問題が修正されます。スティーブン、助けてくれてありがとう。バグがまだ存在する場合、または 2.2 用にコンパイルするつもりがなかった場合でも機能していたので、回答を受け入れます。


コードで古いスタイルのレコードを新しいスタイルのレコードに変換する必要がある方法で、データベース スキーマを根本的に変更しているアプリがあります。ユーザーはこのアプリに大量のデータを保存する可能性があるため、データを移植している間 (つまり、ユーザーが最初に目にするものとして)、プログレス バー付きのモーダル ビュー コントローラーを表示しようとしています。このビュー コントローラviewDidAppear:はデータベース トランザクションを開始し、バックグラウンド スレッドを開始して実際の移植を行いperformSelectorInMainThread:withObject:waitUntilDone:ます。このスレッドは、進行状況バーを更新するようにフォアグラウンド スレッドに指示するために使用されることがあります。

問題は、viewDidAppear:2回呼び出されていることです。「トランザクションの開始」ステップが「データベース ビジー」メッセージで失敗するため、これに気付きましたが、ブレークポイントを設定すると、それが実際に 2 回呼び出されていることがわかり-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]ます-[UIViewController modalPresentTransitionDidComplete]。これらの名前はプライベート UIViewController メソッドのように見えるので、これはフレームワークのバグであるか、UIKit が期待していないことを行っていると推測されます。

関連する 2 つのコードの抜粋 (一部の無関係なコードは要約されています):

- (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 にバグレポートを提出する必要がありますか?

4

1 に答える 1

3

これもアプリで見ました。完全に確認したことはありませんが、これが起こっていると思います:

  1. ルートビューをロード
  2. モーダル ビューを読み込む
  3. OS は、ステップ 1 のビューのビューが表示されたという通知を送信します
  4. 現在のビュー コントローラー(この例ではたまたま DatabaseController クラス) がそれを取得します。
  5. OS はモーダル ビューのビューが表示されたという通知を送信します
  6. 現在のView Controllerが通知を受け取ります。この場合、前回とまったく同じコントローラーです

私の場合、への最初の呼び出しで起こったことをリセットしましたviewDidAppear:

あなたの場合、2 つのオプションが頭に浮かびます。アップグレードを既に開始しているかどうかを追跡する静的変数です。または、UIView*開始する前に渡されたパラメーターを確認してください。

于 2009-03-06T15:54:02.767 に答える