没有情节提要的 UIViewController 状态恢复不起作用

Posted

技术标签:

【中文标题】没有情节提要的 UIViewController 状态恢复不起作用【英文标题】:UIViewController state restoration without storyboard not working 【发布时间】:2013-06-03 02:28:40 【问题描述】:

我想在不使用情节提要的 ios 6 应用中实现状态保存和恢复。我想要保存状态和恢复的主视图控制器是 UIViewController,它是 UINavigationController 的一部分。

我的视图控制器扩展了 UIViewControllerRestoration 协议。我想我正在实现所有必要的方法,但我没有看到模拟器对 encodeRestorableStateWithCoder 或 decodeRestorableStateWithCoder 的任何调用。

这是我的应用委托的外观: MyAppDelegate:

- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder 
    NSLog(@"shouldSaveApplicationState"); // seeing this in the debug window
    return YES;


- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder 
    NSLog(@"shouldRestoreApplicationState"); // seeing this in the debug window
    return YES;


- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder 
    NSLog(@"willEncodeRestorableStateWithCoder"); // seeing this in the debug window


- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder 
    NSLog(@"didDecodeRestorableStateWithCoder"); // seeing this in the debug window

我在调试窗口中看到了所有这些调用。这是我的 MyMainViewController(在应用挂起时可见)的样子:

@interface MyMainViewController : UIViewController <UIViewControllerRestoration>
@end

@implementation MyMainViewController

- (id)init 
    if (self = [super init]) 
        self.restorationIdentifier = @"MyViewControllerRestoreId";
        self.restorationClass = [self class];
    
    return self;


- (void)loadView 
    self.view = [[UIView alloc] initWithFrame:frame];

    // Bunch of work to create my custom views


- (void)awakeFromNib 
    self.restorationClass = [self class];


// Expected a call to this method, but not seeing it in debug window
+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents
                                                            coder:(NSCoder *)coder 
    NSLog(@"viewControllerWithRestorationIdentifierPath: %@", identifierComponents);

    MyMainViewController *vc = [[MyMainViewController alloc] init];
    vc.restorationIdentifier = [identifierComponents lastObject];
    vc.restorationClass = [MyMainViewController class];

    return vc;


// Expected a call to this method, but not seeing it in debug window    
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder 
    NSLog(@"encodeRestorableStateWithCoder");
    [super encodeRestorableStateWithCoder:coder];


// Expected a call to this method, but not seeing it in debug window    
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder 
    NSLog(@"decodeRestorableStateWithCoder");
    [super decodeRestorableStateWithCoder:coder];
    
@end

我用模拟器测试保存和恢复的方式:

1. Launch app in Simulator via Xcode
2. Invoke the Home key so App is now suspended. This where I see:
    shouldSaveApplicationState  
    willEncodeRestorableStateWithCoder
3. End the debugging session in XCode (Command .)
4. Start a new debug session of the app in XCode. I see:
    shouldRestoreApplicationState
    didDecodeRestorableStateWithCoder

我不确定我还缺少什么来完成这项工作。

【问题讨论】:

你有这个工作吗?我被困在这里:( @Jonas Gardner:您找到问题所在了吗?我也有这个问题。谢谢! 【参考方案1】:

我遇到了完全相同的问题。结果,我需要在视图控制器上显式设置协议才能使用 restoreClass:

<UIViewControllerRestoration>

看起来你已经完成了,但最终还是为我完成了。

【讨论】:

你能发布一些 UIViewControllerRestoration 的示例代码吗?我按照你说的试过了,但是没有用。我没有使用故事板。谢谢!【参考方案2】:

此代码可能未运行:

- (id)init 
    if (self = [super init]) 
        self.restorationIdentifier = @"MyViewControllerRestoreId";
        self.restorationClass = [self class];
    
    return self;

视图控制器的指定初始化程序是initWithNibName:bundle:,因此不能保证它的init 会被调用。另外,如果视图控制器来自 xib 或情节提要,则这些方法都不会被调用。

您确实有一个 awakeFromNib 实现:

- (void)awakeFromNib 
    self.restorationClass = [self class];

如果视图控制器来自 xib 或故事板,它将运行,但在这种情况下,您忘记分配 restorationID

【讨论】:

【参考方案3】:

不知道这是否会有所帮助或有所作为,因为我自己只是在学习状态保存/恢复,但这里有一些你可以尝试从我正在学习的教程中得到的东西。

如果您的 VC 在 TabBar 或 NavController 中,请确保它们也有 restoreIdentifier。

【讨论】:

你用的是哪个教程? 这将是 iOS 6 By Tutorials 的电子书,可在此处找到 raywenderlich.com/store/ios-6-by-tutorials 那个网站有很多很棒的免费教程,但是书中有特别之处。我拥有 iOS 5 和 6 书籍。并计划在可用时购买 iOS 7 书籍。在我看来,物有所值。 确认一下,本教程没有使用故事板进行状态保存和恢复? 没有,本教程专门使用情节提要。事实上,我唯一遇到的状态恢复不工作的问题是一个 VC 从一个不在故事板上的笔尖以模态方式呈现。将 VC 放入故事板工作正常,将其放入外部 xib 没有任何其他更改,也没有任何乐趣。

以上是关于没有情节提要的 UIViewController 状态恢复不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何为没有情节提要的 UIViewController (Swift) 提供标识符?

如何在没有情节提要的 Xamarin.iOS UIViewController 中设置 RestorationClass?

为啥情节提要 ui 元素未显示在 xcode 9 中的 UIViewController 上

UIViewController 内容未显示在情节提要上

从情节提要中模拟 UIViewController

从情节提要“Main”中实例化具有标识符“UIViewController-ZWG-5q-24I”的视图控制器,但没有获得 UITableView。