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

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

问题描述

任何想法在 NSViewController 的最佳做法是什么?文档/ MacOSX / Conceptual / OSX_Technology_Overview / CocoaApplicationLayer / CocoaApplicationLayer.html#// apple_ref / doc / uid / TP40001067-CH274-SW8>简历(用户界面保存)用途?我试着将它存储在窗口控制器的 encodeRestorableStateWithCoder:方法只是为了发现视图控制器不会解压缩 restoreStateWithCoder:被调用。

  // NSWindowController子类

- (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){
//因为contentViewController总是出来的,所以这里永远不会执行nil
self.contentViewController = contentViewController;
}
}

请注意,此视图控制器包含其他视图控制器自己的子视图,因此需要在 NSCoder 实例中进行一些范围设置 - 只需将提供的 coder 对象向下传递即可

解决方案



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



在OS X Yosemite它应该工作,因为 NSWindow 现在对NSViewControllers有真正的支持,但它在我的测试用例中不支持。我想这是因为一个需要链接NSViewControllers使用新的API添加/删除他们vs创建他们在一边,只是直接添加他们的视图到窗口。



这里是如何让它总是工作:简单地代理恢复API调用之间的 NSView NSViewController



子类 NSView 像这样:

  @interface GIView:NSView 
@property ,weak)GIViewController * viewController; //避免保持循环!
@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; //这会立即加载视图作为副作用
}
return self;
}

- (void)dealloc {
self.view.viewController = nil; //如果有人仍然保留视图
}

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

@end

现在可以调用 -invalidateRestorableState NSViewController 子类和Cocoa,认为它正在与 NSView ,将在 NSViewController上自动调用 -encodeRestorableStateWithCoder: -restoreStateWithCoder: code>需要的子类。


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

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.

Thanks in advance!

解决方案

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.

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.

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

Subclass NSView like this:

@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

And NSViewController like this:

@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

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天全站免登陆