iOS 6 - Государственное сохранение и восстановление
Я реализовал API iOS 6 для экономии состояния, он работает - после того, как я покинул приложение и запустил его за несколько миллисекунд, обновленный контроллер просмотра влетает, но затем он заменяется основным контроллером представления, отображаемым при запуске.
Я устанавливаю каждый раз, когда приложение запускает корневой вид главного окна, поэтому это должно быть проблемой.
Вот мой код:
- (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;
}
});
}
Вы можете видеть, что in - (void) commonInitializationLaunching: (NSDictionary *) launchOptions Я устанавливаю свой вид корневого окна. Я не знаю, что там положить. Возможно, проверьте, сохранено ли состояние, а затем загрузите этот метод? Но как?
Благодарю!
Вот что я пробовал после Роба:
- (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;
}
без ничего в willFinishLaunching
... Я также удалил оконный код из моего метода commonInitializationLaunching
.
Ответы
Ответ 1
Раскадровка сделает большую часть тяжелой работы для вас, например, восстановление окна. Однако использование кода не приведет к восстановлению окна. Вы должны будете держаться за свой контроллер корневого представления с помощью энкодера. Ваш код будет выглядеть примерно так:
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
и UITabBarController
имеют идентификаторы восстановления.
Ответ 2
Государственная реставрация, как правило, интегрирована с раскадровки. Если вы используете раскадровку, вам не следует создавать собственное окно, просматривать контроллеры и т.д. Вы должны позволить раскадровке сделать это за вас. Что происходит, так это то, что раскадровка выполняет все государственное восстановление, а затем вы создаете новое окно и кладете его поверх всего этого. В этом случае вы, вероятно, создаете две копии вашего пользовательского интерфейса при каждом запуске. Ты просто не замечаешь этого.
Если вы создаете весь свой код в коде (не рекомендуется, но он работает), вам необходимо определить, произошло ли восстановление состояния перед созданием вашего пользовательского интерфейса. Это довольно просто:
-
В вашем commonInitializationLaunching:
инициализируйте только элементы, отличные от UI (вещи, которые никогда не были бы в сохранении состояния). Это место для обработки вещей, на которые могут опираться элементы пользовательского интерфейса во время восстановления состояния. У вас нет ни одного из них в вашем текущем коде.
-
В application:didDecodeRestorableState:
установите делегат приложения ivar, чтобы указать, что состояние было восстановлено.
-
В application:didFinishLaunchingWithOptions:
после запуска commonInitializationLaunching:
проверьте свой ivar. Если состояние не было восстановлено, создайте пользовательский интерфейс.
Помните, что commonInitializationLaunching:
существует только для обратной совместимости с iOS 5. Если вам это не нужно, то просто поместите не-интерфейс в willFinish
и UI в didFinish
(если состояние не было восстановлено).