知道在resume(用户界面保存)目的窗口内归档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
对象将导致名称冲突档案
提前致谢!
答案 0 :(得分:6)
状态恢复在NSView
上免费工作,但在NSViewController
上被忽略,即使它将方法实现为NSResponder
的子类。我想这是因为窗口不知道NSViewControllers可能拥有它包含的一些视图。
在OS X Yosemite上它应该可以工作,因为NSWindow
现在真正支持NSViewControllers,但它不适用于我的测试用例。我想这是因为我们需要使用新API“链接”NSViewControllers来添加/删除它们,而不是在侧面创建它们,只是将它们的视图直接添加到窗口中。如果你想让你的应用程序在Yosemite之前的系统上运行,那么后者实际上是必需的。
以下是如何使其始终有效:只需在NSView
和NSViewController
之间代理恢复API调用。
子类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
现在您可以从-invalidateRestorableState
子类和Cocoa调用NSViewController
,认为它正在与NSView
对话,会自动调用您的-encodeRestorableStateWithCoder:
和-restoreStateWithCoder:
<{1}}根据需要进行子类化。
答案 1 :(得分:0)
我没有多少与可恢复状态混淆(Jonathon Mah为DL3做了它)但是如果我这样做,我会尝试删除这两种方法并实现+ restorableStateKeyPaths,例如:
+ (NSArray *)restorableStateKeyPaths;
{
return @[@“contentViewController.firstInterestingStateProperty”, @“contentViewController.secondInterestingStateProperty”];
}
看看机器是否为我处理了这一切。
+ (NSArray *)restorableStateKeyPaths;
返回一组键路径,表示属性的路径 应该坚持不懈。框架将通过观察这些关键路径 KVO并自动将其值保留为持久性的一部分 状态,并在重新启动时恢复它们。关键路径的值 应该实现密钥存档。基础实现返回一个 空数组。