2012-09-24 30 views
11

Implementé iOS 6 API para ahorrar estados, funciona: después de salir de la aplicación y volver a iniciarla durante unos milisegundos, el controlador de vista restaurado vuelve volando, pero luego se reemplaza por la vista principal controlador que visualizo en el lanzamiento.iOS 6 - Preservación y restauración del estado

Estoy configurando cada vez que la aplicación inicia la vista raíz de la ventana principal, por lo que este debe ser el problema.

Aquí está mi código:

- (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; 
     } 
    }); 
} 

se puede ver que en - (void) commonInitializationLaunching: (NSDictionary *) launchOptions Soy la creación de vista raíz de mi ventana. No sé qué poner ahí. Quizás verifique si hay estado guardado y luego cargue este método? ¿Pero cómo?

Gracias!

Aquí es lo que he intentado seguir el consejo de Rob:

- (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; 
} 

con nada en willFinishLaunching ... También quité por código ventana de mi método commonInitializationLaunching.

+0

¿Ha ayudado mi respuesta alguna? Algunos comentarios serían geniales. – rbrown

Respuesta

24

Los guiones gráficos le harán la mayor parte del trabajo pesado, como restaurar la ventana. Sin embargo, el uso de código no restaurará la ventana. Tendrá que aferrarse a su controlador de vista raíz utilizando el codificador.Su código se verá algo como esto:

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; 
} 

Otra Gotcha a tener en cuenta es asegurarse de que sus UINavigationController s y s UITabBarController tienen identificadores de restauración.

+0

a la que responde parece realmente lógico, aunque no pude implementarlo en mi programa de prueba, y lo dejé para otro momento. ¡Gracias por la gran respuesta! – Devfly

6

La restauración de estado generalmente se integra con guiones gráficos. Si está utilizando un guión gráfico, no debería crear su propia ventana, ver controladores, etc. Debería dejar que el guión lo haga por usted. Lo que sucede es que el guión gráfico está haciendo toda la restauración del estado, y luego estás creando una nueva ventana y poniéndolo encima de todo eso. Si ese es el caso, probablemente esté creando dos copias de su UI en cada lanzamiento. Simplemente no lo estás notando.


Si usted está construyendo toda su interfaz en el código (no es un método recomendado, pero funciona), a continuación, es necesario determinar si la restauración del estado ocurrió antes de crear la interfaz de usuario. Esto es bastante simple:

  • En su commonInitializationLaunching:, inicializar sólo los elementos de interfaz de usuario (no cosas que no volvería a ser en el estado de conservación). Este es el lugar para manejar cosas en las que los elementos de la IU pueden confiar durante la restauración del estado. No tiene ninguno de estos en su código actual.

  • En application:didDecodeRestorableState:, establezca una aplicación delegada ivar para indicar que se restauró el estado.

  • En application:didFinishLaunchingWithOptions:, después de ejecutar commonInitializationLaunching:, revise su ivar. Si el estado no se restauró, crea una UI.

Recuerde que el patrón commonInitializationLaunching: sólo existe para la compatibilidad con iOS 5. Si no es necesario que, a continuación, sólo hay que poner no en la interfaz de usuario y la interfaz de usuario en willFinishdidFinish (si el estado no se ha restaurado) .

+0

No estoy usando guiones gráficos. – Devfly

+0

Un enfoque realmente agradable, pero lo único que obtengo ahora es una pantalla negra: cuando muevo '' selfWindows makeKeyAndVisible'' para que dependa de iVar 'isRestored', incluso lo intenté con la simple aplicación Master-Detail con Storyboard, y no lo hice. funcionó .. ¿Hay algo de lo que me estoy perdiendo? – Devfly

+0

Debe llamar a -makeKeyAndVisible en todos los casos. Solo debe * crear * una ventana UI cuando no esté restaurando. –

Cuestiones relacionadas