【问题标题】:How do views load on OSX 10.9?视图如何在 OSX 10.9 上加载?
【发布时间】:2015-10-12 21:04:02
【问题描述】:

我只在 OSX 10.10+ 上进行开发,我希望我的应用程序可以在 10.9 和 10.10+ 上运行。我遇到的 viewDidLoad() 问题仅在 10.10+ 上可用。如何灵活地处理视图和视图控制器?

从查看源代码看来,我需要重写 init?但是当覆盖 init:nibName:nibBundleOrNil: 但它也需要 init:coder 时,这对我来说没有多大意义(它在源代码中没有记录)。

【问题讨论】:

  • 重载loadView 能解决问题吗?您也可以尝试为 view 属性添加 didSet,但鉴于它是只读属性,这会导致未记录的行为。

标签: macos swift cocoa osx-mavericks


【解决方案1】:

在 10.10 之前,NSViewController 基本上什么都不做(它是 NSWindowController 完成了大部分工作);)在 10.10 上,它获得了与 iOS 世界类似的方法(viewDidLoad...),一件非常重要的事情,终于被放置了自动进入 NSResponder 链(NSApp sendAction:... 会检查 viewController 是否有方法)。

那么如何获得功能呢?

  1. 使用 awakeFromNib
  2. 手动将视图添加到响应者链中(如果使用 10.10 SDK 编译,则视图会在 10.10 及更高版本自动添加;如果使用 10.9 SDK 编译,则必须手动添加)
  3. 使用 XIB;你不能使用故事板 -> 他们使用 10.10 nsviewcontrollers -> 死胡同

因此,如果您使用情节提要,则需要做很多工作。如果你没有干净的 MVC/MVVM 架构,那就不值得了。

另一种方法是将 10.10 之前和 10.10 之后的课程增加一倍,但这意味着将相同的代码放置两次(一次使用情节提要,一次使用 XIB)。

编辑:

正如@geowar 建议的那样,您可以覆盖 loadView。请注意,您仍然不能使用情节提要,您必须手动将 viewController 添加到响应者链中

- (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

EDIT2:

awakeFromNib 在 loadView 之后调用(从 xib 获取新视图并实例化它)。正如@Daij-Djan 所建议的那样,另一种解决方案是覆盖 setter。

给正在寻找 -viewWillLoad 和 -viewDidLoad 的人的建议 NSViewController 中的方法

即使 NSWindowController 有 -windowWillLoad 和 -windowDidLoad 覆盖 NSViewController 类的方法 Mac OS 10.5 没有对应的 -viewWillLoad 和 -viewDidLoad 方法。您可以覆盖 -[NSViewController loadView] 来自定义 笔尖加载完成之前或之后立即发生的情况 通过视图控制器。

【讨论】:

  • 见:stackoverflow.com/questions/30174952/…>
  • 谢谢。我将其添加到我的答案中。无法使用情节提要,并且响应者链按我描述的那样工作。
  • 这是错误的 - 你可以使用任何你喜欢的东西 - 因为在视图存在之后调用 xib awakeFromNib .. 这是不完整的
【解决方案2】:

让你在 10.9 上相当于 10.10 编写这样的 VC

@interface MyViewController : NSViewController 
@end

@implementation MyViewController 
- (void)setView:(NSView*)v {
    super.view = v;
    // if we're running on 10.8 or older…
    if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_8) {
        [self viewDidLoad]; // call viewDidLoad (added in 10.9)
    }
}
@end

【讨论】:

  • 你是对的,但你不能称之为等价物。仅通过这样做,您无法获得与 NSViewController 行为相同的功能。特别是如果他使用故事板,这对于 10.9 来说是一个死胡同。
  • 为什么?如果这还不够,如果不调用 setView,他甚至可以去覆盖 awakeFromNib。不明白:)
  • 在 97% 的情况下就足够了,而且你是 100% 正确的 ;)
猜你喜欢
  • 2013-11-30
  • 2013-11-03
  • 2014-08-23
  • 2013-06-23
  • 1970-01-01
  • 2013-12-27
  • 2014-08-22
  • 2014-04-12
相关资源
最近更新 更多