为 Lion 的用户界面恢复功能编码 NSViewController [英] Encoding NSViewController for Lion's user interface resume feature

查看:23
本文介绍了为 Lion 的用户界面恢复功能编码 NSViewController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

知道在 简历(用户界面保存)目的?我尝试在窗口控制器的 encodeRestorableStateWithCoder: 方法中归档它,结果发现当 restoreStateWithCoder: 被调用时,视图控制器没有被取消归档.

Any idea what are the best practices for archiving an NSViewController inside a window for resume (user interface preservation) purposes? I've tried archiving it in the window controller's encodeRestorableStateWithCoder: methods only to find out that the view controller doesn't get unarchived when restoreStateWithCoder: is called.

// NSWindowController subclass

-(void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super encodeRestorableStateWithCoder:coder];
    NSViewController* contentViewController = self.contentViewController;
    if (contentViewController) {
        [coder encodeObject:contentViewController forKey:BSContentViewControllerResumeKey];
    }
}

-(void)restoreStateWithCoder:(NSCoder *)coder
{
    [super restoreStateWithCoder:coder];
    NSViewController* contentViewController = [coder decodeObjectForKey:BSContentViewControllerResumeKey];
    if (contentViewController) {
        // somehow this never get executed since contentViewController always comes out nil
        self.contentViewController = contentViewController;
    }
}

请注意,此视图控制器包含管理自己的子视图的其他视图控制器,因此需要在 NSCoder 实例中进行一些范围界定 - 只需向下传递提供的 coder 对象将导致存档中的名称冲突.

Note that this view controller contains other view controllers that manages their own subviews, and thus will need some scoping in the NSCoder instance – simply passing the provided coder object downwards will cause name clashes in the archive.

提前致谢!

推荐答案

状态恢复在 NSView 上免费工作,但在 NSViewController 上被忽略,即使它实现了方法NSResponder 的子类.我想这是因为窗口不知道 NSViewControllers 可能拥有它包含的一些视图.

State restoration works for free on NSView but is ignored on NSViewController even though it implements the methods as a subclass of NSResponder. I suppose that's because the window doesn't know about NSViewControllers that may own some of the views it contains.

在 OS X Yosemite 上它应该可以工作,因为 NSWindow 现在真正支持 NSViewControllers,但在我的测试用例中没有.我想这是因为需要使用新的 API 来链接" NSViewControllers 来添加/删除它们,而不是在侧面创建它们并将它们的视图直接添加到窗口中.如果您想让您的应用程序在优胜美地之前的系统上运行,则实际上需要后者.

On OS X Yosemite it's supposed to work since NSWindow now has real support for NSViewControllers, but it doesn't in my test cases. I guess it's because one needs to "chain" the NSViewControllers using the new APIs to add / remove them vs creating them on the side and just adding their views directly to the window. The latter is actually required if you want to have your app run on pre-Yosemite systems anyway.

以下是让它始终工作的方法:只需在 NSViewNSViewController 之间代理恢复 API 调用.

Here's how to make it always work: simply proxy the restoration APIs calls between NSView and NSViewController.

子类 NSView 像这样:

@interface GIView : NSView
@property(nonatomic, weak) GIViewController* viewController;  // Avoid retain-loops!
@end

@implementation GIView

- (void)setViewController:(GIViewController*)viewController {
  _viewController = viewController;
}

- (void)encodeRestorableStateWithCoder:(NSCoder*)coder {
  [super encodeRestorableStateWithCoder:coder];

  [_viewController encodeRestorableStateWithCoder:coder];
}

- (void)restoreStateWithCoder:(NSCoder*)coder {
  [super restoreStateWithCoder:coder];

  [_viewController restoreStateWithCoder:coder];
}

@end

NSViewController 像这样:

@interface GIViewController : NSViewController
@end

@implementation GIViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
  if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
    self.view.viewController = self;  // This loads the view immediately as a side-effect
  }
  return self;
}

- (void)dealloc {
  self.view.viewController = nil;  // In case someone is still retaining the view
}

- (void)invalidateRestorableState {
  [self.view invalidateRestorableState];
}

@end

现在你可以从 NSViewController 子类和 Cocoa 调用 -invalidateRestorableState,认为它正在与一个 NSView 对话,会自动调用 -encodeRestorableStateWithCoder:-restoreStateWithCoder: 根据需要在 NSViewController 子类上.

Now you can call -invalidateRestorableState from the NSViewController subclass and Cocoa, thinking it's talking to an NSView, will automatically call -encodeRestorableStateWithCoder: and -restoreStateWithCoder: on your NSViewController subclass as needed.

这篇关于为 Lion 的用户界面恢复功能编码 NSViewController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆