我只在 OSX 10.10+ 上进行开发,我希望我的应用程序能够在 10.9 和 10.10+ 上运行。我遇到的问题是 viewDidLoad() 仅适用于 10.10+。我如何才能灵活地使用 View 和 View Controller 来同时处理这两者?
从查看源代码看来我需要重写 init?但是当覆盖 init:nibName:nibBundleOrNil: 但它也需要 init:coder 并且这对我来说没有多大意义(它在源代码中没有记录)。
最佳答案
在 10.10 之前,NSViewController 基本上什么都不做(它是 NSWindowController 做的大部分工作);)在 10.10 上,它获得了与 iOS 世界类似的方法(viewDidLoad ...)和一件非常重要的事情,它终于被放置自动进入 NSResponder 链(NSApp sendAction:... 将检查 viewController 是否有该方法)。
那么如何获取功能呢?
- 使用 awakeFromNib
- 手动将 View 添加到响应链(如果使用 10.10 SDK 编译,则 View 会在 10.10 及更高版本上自动添加;如果使用 10.9 SDK 编译,则必须手动添加)
- 使用 XIB;你不能使用 Storyboard -> 他们使用 10.10 nsviewcontrollers -> 死胡同
因此,如果您使用 Storyboard,工作量会很大。如果您没有干净的 MVC/MVVM 架构,那么它就不值得。
替代方案是将 10.10 之前和 10.10 之后的类(class)加倍,但这意味着将相同的代码裁员两次(一次使用 Storyboard,一次使用 XIB)。
编辑:
正如@geowar 建议的那样,您可以覆盖 loadView。请注意,你仍然不能使用 Storyboard,你必须手动将你的 viewController 添加到 responderChain
- (void)loadView
{
[super loadView];
// if we're running on 10.8 or older…
if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_8) {
[self viewDidLoad]; // call viewDidLoad (added in 10.9)
}
}
或者
- (void)setView:(NSView*)view {
super.view = view;
// if we're running on 10.8 or older…
if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_8) {
[self viewDidLoad]; // call viewDidLoad (added in 10.9)
}
}
@end
编辑2:
awakeFromNib 在 loadView 之后调用(它从 xib 获取新 View 并实例化它)。正如@Daij-Djan 所建议的,另一种解决方案是覆盖 setter。
Advice for People who Are Looking for -viewWillLoad and -viewDidLoad Methods in NSViewController
Even though NSWindowController has -windowWillLoad and -windowDidLoad methods for you to override the NSViewController class introduced in Mac OS 10.5 does not have corresponding -viewWillLoad and -viewDidLoad methods. You can override -[NSViewController loadView] to customize what happens immediately before or immediately after nib loading done by a view controller.
关于macos - View 如何在 OSX 10.9 上加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33090174/