2012-09-24 25 views
11

状態を保存するためにiOS 6 APIを実装しました。動作します。アプリを終了して数ミリ秒間起動した後、リストアされたビューコントローラが起動しますが、コントローラの起動時に表示されます。iOS 6 - 状態の保存と復元

アプリがメインウィンドウのルートビューを起動するたびに設定するので、これは問題である必要があります。私は私の窓のルートビューを設定しています(NSDictionaryの*)launchOptions : - (無効)commonInitializationLaunching

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    [self commonInitializationLaunching:launchOptions]; 
    return YES; 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    [self commonInitializationLaunching:launchOptions]; 
    return YES; 
} 

- (void)commonInitializationLaunching:(NSDictionary *)launchOptions 
{ 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 

     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
     // Override point for customization after application launch. 
     static NSString *const kKeychainItemName = @"OAuthGoogleReader"; 
     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 
     self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController]; 

     GTMOAuth2Authentication *auth; 
     auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName 
                    clientID:kClientID 
                   clientSecret:kClientSecret]; 

     self.window.rootViewController = self.navController; 

     [self.window makeKeyAndVisible]; 

     BOOL isSignedIn = [auth canAuthorize]; 
     if (isSignedIn) { 
      NSLog(@"Signed"); 
     }else{ 
      NSString *scope = @"https://www.google.com/reader/api/"; 

      GTMOAuth2ViewControllerTouch *viewController; 
      viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:scope 
                     clientID:kClientID 
                    clientSecret:kClientSecret 
                   keychainItemName:kKeychainItemName 
                     delegate:self 
                   finishedSelector:@selector(viewController:finishedWithAuth:error:)]; 
      [self.navController pushViewController:viewController animated:YES]; 
      //  self.window.rootViewController = viewController; 
     } 
    }); 
} 

あなたはその中を見ることができます:

は、ここに私のコードです。私はそこに何を入れるべきか分からない。保存された状態が存在するかどうかを確認し、このメソッドをロードしますか?しかしどうですか?

ありがとうございます!私も私のcommonInitializationLaunching方法から窓コードによって除去 ... willFinishLaunchingに何も

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    if (!self.isRestored) { 
     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    } 
    [self commonInitializationLaunching:launchOptions]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

:ここ

は、私はロブのアドバイスを、次の試してみたものです。

+0

私の答えは助けられましたか?いくつかのフィードバックは素晴らしいでしょう。 – rbrown

答えて

24

ストーリーボードは、ウィンドウの復元など、大部分の作業を行います。ただし、コードを使用すると、ウィンドウは復元されません。エンコーダを使用してルートビューコントローラを固定する必要があります。あなたのコードは次のようになります:

NSString * const AppDelegateRootVCKey = @"AppDelegateRootVCKey"; 

- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder { 
    [coder encodeObject:self.window.rootViewController forKey:AppDelegateRootVCKey]; 
} 

- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder { 

    // Grabs the preserved root view controller. 
    UIViewController * vc = [coder decodeObjectForKey:AppDelegateRootVCKey]; 

    if (vc) { 
     UIWindow * window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
     window.rootViewController = vc; 
     window.restorationIdentifier = NSStringFromClass([window class]); 

     // The green color is just to make it obvious if our view didn't load properly. 
     // It can be removed when you are finished debugging. 
     window.backgroundColor = [UIColor greenColor]; 

     self.window = window; 
    } 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    if (!self.window) { 

     UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

     // The blue color is just to make it obvious if our view didn't load properly. 
     // It can be removed when you are finished debugging. 
     window.backgroundColor = [UIColor blueColor]; 

     UIViewController *root = // However you create your root. 

     window.rootViewController = root; 
     window.restorationIdentifier = NSStringFromClass([window class]); 

     self.window = window; 
    } 

    [self commonInitializationLaunching:launchOptions]; 
    [self.window makeKeyAndVisible]; 

    return YES; 
} 

に注意するもう一つの落とし穴は、あなたのUINavigationController sおよびUITabBarController sが復元識別子を持っていることを確認することです。

+0

答えは本当に論理的ですが、テストプログラムでは実装できませんでした。素晴らしい答えをありがとう! – Devfly

6

状態復元は、一般にストーリーボードと統合されています。ストーリーボードを使用している場合は、独自のウィンドウを作成したり、コントローラを表示したりしてはいけません。ストーリーボードを使用してください。起こっているのは、ストーリーボードがすべての状態を復元していることです。そして、新しいウィンドウを作成し、すべてのものの上に置いています。その場合、毎回の起動時にUIのコピーを2つ作成することになります。あなたはそれに気づいていないだけです。


あなたがコードの中であなたの全体のインタフェースを構築している(いない推奨されるアプローチが、それは仕事をする)場合は、状態の復元があなたのUIを作成する前に起こったかどうかを判断する必要があります。あなたのcommonInitializationLaunching:

  • 、唯一の非UI要素(これまでの状態の保存ではないだろうもの)を初期化します。これは非常に簡単です。これは、状態の復元中にUI要素が依存する可能性のある事項を処理する場所です。あなたは現在のコードにこれらのどれも持っていません。

  • application:didDecodeRestorableState:には、状態が復元されたことを示すアプリケーションデリゲートivarを設定します。

  • application:didFinishLaunchingWithOptions:で、commonInitializationLaunching:を実行した後、ivarを確認してください。状態が復元されなかった場合は、UIを作成します。

あなたは(状態が復元されなかった場合)、そしてちょうどdidFinishwillFinishに非UIを入れて、UI、ことを必要としない場合commonInitializationLaunching:パターンが唯一のiOS 5との後方互換性のために存在していることを覚えていますか。

+0

私はストーリーボードを使用していません。 – Devfly

+0

本当に素敵なアプローチですが、今私が得るのは黒いスクリーンです - 私が自分の '[self.windows makeKeyAndVisible]'をiVar 'isRestored'に依存するように動かすと、Storyboardを使った簡単なマスターディテールアプリで試してみました。私は行方不明のものがありますか? – Devfly

+0

すべての場合に-makeKeyAndVisibleを呼び出す必要があります。復元しないときはUIWindowを*作成するだけです。 –

関連する問題