iOS状态恢复丢弃导航堆栈

far*_*ski 5 uiviewcontroller uinavigationcontroller ios state-restoration ios7

tl; dr状态恢复过程似乎正在发生,但堆栈(非根)视图控制器在恢复完成后不会在应用程序中结束.

我正在尝试在应用程序中实现状态恢复,该应用程序不使用任何.nib或故事板.这是一个相当基本的结构:窗口rootViewControllerUINavigationController自己的rootViewController和所有其他子视图控制器UITableViewControllers(例如,Window> Nav Ctrl> Table View Ctrl> Table View Ctrl>等).没有任何视图控制器被重复(即堆栈中的每个项目都是不同的UITableViewController子类)

如我正在与故事板创建任何视图控制器,I为每个视图控制器类设置指定初始化restorationIdentifierrestorationClass.

当应用程序正在恢复时,我看到当应用程序进入后台时存在的每个视图控制器发生解码(例如,导航控制器,播客列表控制器和播客详细控制器),但最终结果是恢复始终是导航控制器,显示正常的根视图控制器(播客列表控制器).

这个问题似乎很相似了这个问题,但我肯定调用superencode-和decodeRestorableStateWithCoder:我的视图控制器方法(如果存在的话),这样的解决方案并不能帮助我.

我观看了WWDC视频并经历了许多教程,虽然我似乎达到了所有要求,但事情并没有按照应有的方式发挥作用.

我能想到的唯一事情是恢复正在发生,但我的默认初始化代码正在用一个仅包含根的"新鲜"替换恢复的导航视图控制器堆栈.根据WWDC视频,窗口和根视图控制器应该在状态恢复之前正常设置,并且不应该影响恢复的最终应用程序状态.

我想我的一个问号是我的viewControllerWithRestorationIdentifierPath:方法应该发生什么UINavigationController.应该rootViewController像我一样设置吗?如果没有,还会发生什么?我实际上找不到任何正在恢复导航控制器的工作示例代码,而且它不是从笔尖或故事板创建的.除此之外,我很难过.

实施代码

FLAppDelegate.m

# pragma mark - UIApplicationDelegate
# pragma mark Monitoring App State Changes

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

  // Window and root VC set up in window getter
  [self.window makeKeyAndVisible];

  return YES;
}

# pragma mark Managing App State Restoration

- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder {
  return YES;
}

- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder {
  return YES;
}

#pragma mark Providing a Window for Storyboarding

- (UIWindow *)window {
  if (!_window) {
    _window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
    _window.rootViewController = self.navigationController;
  }

  return _window;
}

- (FLNavigationController *)navigationController {
  if (!_navigationController) {
    FLPodcastTableViewController* podcastViewController = [[FLPodcastTableViewController alloc] initWithStyle:UITableViewStylePlain];
    _navigationController = [[FLNavigationController alloc] initWithRootViewController:podcastViewController];
  }

  return _navigationController;
}
Run Code Online (Sandbox Code Playgroud)

FLNavigationController.m

- (id)initWithRootViewController:(UIViewController *)rootViewController {
  self = [super initWithRootViewController:rootViewController];
  if (self) {
    self.restorationIdentifier = @"FLNavigationController";
    self.restorationClass = self.class;
  }
  return self;
}

#pragma mark - UIViewControllerRestoration

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder {
  FLPodcastTableViewController* podcastViewController = [[FLPodcastTableViewController alloc] initWithStyle:UITableViewStylePlain];
  return [[self alloc] initWithRootViewController:podcastViewController];
}
Run Code Online (Sandbox Code Playgroud)

FLPodcastTableViewController.m

- (id)initWithStyle:(UITableViewStyle)style {
  self = [super initWithStyle:style];
  if (self) {
    [self.tableView registerClass:FLPodcastTableViewCell.class forCellReuseIdentifier:FLPodcastTableViewCellIdentifier];

    self.restorationIdentifier = @"FLPodcastTableViewController";
    self.restorationClass = self.class;
  }
  return self;
}

#pragma mark - UIViewControllerRestoration

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder {
  return [[self alloc] initWithStyle:UITableViewStylePlain];
}
Run Code Online (Sandbox Code Playgroud)

FLPodcastEpisodeTableViewController.m

- (id)initWithPodcast:(FLPodcast *)podcast {
  self = [self initWithStyle:UITableViewStylePlain];
  if (self) {
    self.podcast = podcast;

    self.restorationIdentifier = @"FLPodcastEpisodeTableViewController";
    self.restorationClass = self.class;

    [self.tableView registerClass:FLPodcastEpisodeTableViewCell.class forCellReuseIdentifier:FLPodcastEpisodeTableViewCellIdentifier];
  }
  return self;
}

#pragma mark - UIViewControllerRestoration

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder {
  FLPodcastEpisodeTableViewController* viewController = nil;

  NSString* podcastURI = [coder decodeObjectForKey:kPodcastURLKey];
  NSURL* podcastURL = [NSURL URLWithString:podcastURI];

  FLPodcast* podcast = [FLPodcast podcastWithURL:podcastURL];

  if (podcast) {
    viewController = [[self alloc] initWithPodcast:podcast];
  }

  return viewController;
}

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
  [coder encodeObject:self.podcast.feedURL.absoluteString forKey:@kPodcastURLKey];

  [super encodeRestorableStateWithCoder:coder];
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
  [super decodeRestorableStateWithCoder:coder];
}
Run Code Online (Sandbox Code Playgroud)