【问题标题】:Loading View From XIB and getting nil macOS app从 XIB 加载视图并获取 nil macOS 应用程序
【发布时间】:2017-12-27 18:14:46
【问题描述】:

我正在尝试从 xib 文件加载视图。我想做的事情对我来说似乎很简单,但由于某种原因,它比我想象的要困难得多。我只是有一个自定义视图(带有标签、按钮和表格视图),我想在同一个窗口中(在堆栈视图中)多次重复使用它。这是我的自定义视图代码

class PlatformView: NSView {
    @IBOutlet var testLabel: NSTextField!

    required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        self.testLabel.stringValue = "Init"
    }

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // Drawing code here.
    }
}

这是我在视图中的视图确实加载了主视图控制器。我做了两次,因为我在堆栈视图中需要两个相同的视图。问题是我遇到了一个错误。这条线是 nil let topLevelObjects = objectArray2?.firstObject as? PlatformView 并引起了很多问题。这只在我运行应用程序时有时会发生。这是非常随机的,我不知道为什么会这样。有一个更好的方法吗?还是我在代码中做错了什么?

var objectArray:NSArray?
guard let nib = NSNib(nibNamed: NSNib.Name(rawValue: "PlatformView"), bundle: nil) else {return}
if nib.instantiate(withOwner: self, topLevelObjects: &objectArray), let topLevelObjects = objectArray?.firstObject as? PlatformView {
    self.platformStackView.addArrangedSubview(topLevelObjects)
    self.firstPlatformView = topLevelObjects
}

if nib.instantiate(withOwner: self, topLevelObjects: &objectArray), let topLevelObjects = objectArray?.firstObject as? PlatformView {
    self.platformStackView.addArrangedSubview(topLevelObjects)
    self.secondPlatformView = topLevelObjects
}

【问题讨论】:

  • 不能保证firstObject就是你要找的PlatformView。可以有多个顶级对象,因此您应该为所需的 PlatformView 检查它们。在我的测试中,我在 XIB 文件中只有一个视图(带有子视图),但界面构建器还添加了一些我需要忽略的其他内容。在我的测试中,顶层对象是我的 TestView 和 NSApplication 的一个实例。我必须检查数组以获取第二项 TestView。

标签: swift macos swift4


【解决方案1】:

实例化在 XIB 文件中返回一个顶级对象数组,其中一些接口构建器本身可能已添加(如果您真的对此感到好奇,请参阅 XIB 的布局)。

简单的方法是在返回的 topLevelObjects 中搜索您的 PlatformView,如下所示:

if nib.instantiate(withOwner: self, topLevelObjects: &objectArray) {
    for object in topLevelObjects {
        if let platformView = object as? PlatformView {
            self.platformStackView.addArrangedSubview(platformView)
            self.firstPlatformView = platformView
        }
    }
}

但是,假设您确定您的 PlatformView 在 XIB 中,一个更优雅的解决方案是这样的:

if nib.instantiate(withOwner: self, topLevelObjects: &objectArray) {
    if let topLevelObjects = objectArray {
        let platformView = topLevelObjects.flatMap({ object in return object as? PlatformView }).first!
        self.platformStackView.addArrangedSubview(platformView)
        self.firstPlatformView = platformView
    }
}

正如我所说,你必须小心,因为强制解包可选。

【讨论】:

  • 平面图之前的topLevelObjects 指的是什么?如果您打算输入objectArray,那也行不通。第一种方法在我尝试时似乎最初有效,但如果有更优雅的解决方案,我宁愿使用它。
  • 对不起。我已经更新了我的示例,因为我已将可选的 objectArray 解包为一个明确的数组以供使用。
猜你喜欢
  • 1970-01-01
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 2019-04-20
  • 1970-01-01
  • 2017-10-20
  • 2012-05-14
  • 2020-07-06
相关资源
最近更新 更多