8

知道出于恢复(用户界面保留)目的而归档NSViewController窗口内部的最佳实践是什么吗?我已经尝试在窗口控制器的 方法中归档它,只是发现视图控制器在 被调用时没有被取消归档。encodeRestorableStateWithCoder:restoreStateWithCoder:

// 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对象将导致存档中的名称冲突。

提前致谢!

4

2 回答 2

6

状态恢复在上免费工作,NSViewNSViewController即使将方法实现为NSResponder. 我想那是因为窗口不知道可能拥有它包含的某些视图的 NSViewControllers。

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

以下是让它始终工作的方法:只需代理 和 之间的恢复 APINSView调用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

现在您可以-invalidateRestorableStateNSViewController子类和 Cocoa 调用,认为它正在与 an 对话,NSView将根据需要自动调用您的子类。-encodeRestorableStateWithCoder:-restoreStateWithCoder:NSViewController

于 2015-02-21T01:07:58.423 回答
0

我对可恢复状态的处理并不多(Jonathon Mah 是为 DL3 做的),但如果我这样做,我会尝试删除这两个方法并实现 +restorableStateKeyPaths,例如:

+ (NSArray *)restorableStateKeyPaths;
{
    return @[@“contentViewController.firstInterestingStateProperty”, @“contentViewController.secondInterestingStateProperty”];
}

看看机器是否为我处理了这一切。

+ (NSArray *)restorableStateKeyPaths;

返回一组关键路径,表示应该持久的属性的路径。框架将通过 KVO 观察这些关键路径,并自动将它们的值作为持久状态的一部分持久化,并在重新启动时恢复它们。密钥路径的值应该实现密钥归档。基本实现返回一个空数组。

于 2014-01-14T08:19:29.807 回答