以编程方式创建的NSCollectionView`makeItem`即使已注册也会返回nil

时间:2018-05-31 19:30:39

标签: swift macos cocoa appkit nscollectionview

我正在开发一个面向macOS 10.10 SDK并使用Xcode 9.3(Swift 4)的macOS应用程序。我没有使用xib,而是以编程方式创建所有视图。

我想创建一个NSCollectionView。我注册了NSCollectionViewItem的子类,然后通过调用NSCollectionView将该类注册到collectionView.register(:,forItemWithIdentifier)。稍后,在数据源中,我调用collectionView.makeItem(withIdentifier:,for:)

但是makeItem方法总是返回nil。我做错了什么?

我找到了类似的question,但解决方案是调用register,我已经这样做了。

作为参考,这是重现我的问题的最小工作:当我在调用makeItem之后设置断点时,我可以看到返回的值始终为nil

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!


    func applicationDidFinishLaunching(_ aNotification: Notification) {
        window.contentViewController = TestViewController()
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }


}

let cellIdentifier = NSUserInterfaceItemIdentifier(rawValue: "testIdentifier")

class TestViewController: NSViewController, NSCollectionViewDataSource {

    override func loadView() {
        self.view = NSView()
    }

    override func viewDidLoad() {
        let scroll = NSScrollView()

        self.view.addSubview(scroll)

        scroll.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: scroll, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: scroll, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: scroll, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: scroll, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: scroll, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 500).isActive = true
        NSLayoutConstraint(item: scroll, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 500).isActive = true

        let collection = NSCollectionView()
        scroll.documentView = collection

        collection.register(TestViewItem.self, forItemWithIdentifier: cellIdentifier)
        collection.dataSource = self
        collection.collectionViewLayout = NSCollectionViewFlowLayout()
        collection.reloadData()
    }

    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        let item = collectionView.makeItem(withIdentifier: cellIdentifier, for: indexPath)
        return item
    }
}

class TestViewItem: NSCollectionViewItem {

    override func loadView() {
        self.view = NSView()
    }
}

1 个答案:

答案 0 :(得分:4)

我认为这是一个错误。解决方法:在注册课程之前设置collectionViewLayout

显然,如果未设置collectionViewLayout,则不会存储已注册的课程。注册课程后,collectionViewLayout可以设置为新的布局,注册的课程不会被删除。