1

I am trying to create a simple NSCollectionView programmatically. I am setting it up in the NSViewController:

class ViewController: NSViewController {
    var scrollView: NSScrollView!
    var collectionView: NSCollectionView!
    override func loadView() {
        self.view = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView = NSCollectionView(frame: NSZeroRect)
        collectionView.backgroundView?.wantsLayer = true
        collectionView.backgroundColors = [NSColor.black]
        collectionView.collectionViewLayout = NSCollectionViewFlowLayout()
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.register(CollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("CollectionViewItem"))
        scrollView = NSScrollView(frame: view.frame)
        scrollView.documentView = collectionView
        view.addSubview(scrollView)
        self.scrollView.translatesAutoresizingMaskIntoConstraints = false
        self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
    }
}

extension ViewController: NSCollectionViewDataSource {
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }
    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier("CollectionViewItem"), for: indexPath)
        item.representedObject = indexPath.item
        return item
    }
}

extension ViewController: NSCollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
        return NSSize(width: 25, height: 25)
    }
}

Here's how I am setting up the NSCollectionViewItem:

class CollectionViewItem: NSCollectionViewItem {
    var collectionViewItemView: CollectionViewItemView?
    override func loadView() {
        if (self.representedObject != nil) {
            self.collectionViewItemView = CollectionViewItemView(frame: NSZeroRect, number: self.representedObject as! Int)
            self.view = collectionViewItemView!
        } else {
            self.view = CollectionViewItemView(frame: NSZeroRect)
        }
    }
    override var representedObject: Any? {
        didSet {
            loadView()
        }
    }
}

And here's how I'm creating a custom NSView to work inside the NSCollectionViewItem:

class CollectionViewItemView: NSView {
    var number: Int?
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
    }
    convenience init(frame frameRect: NSRect, number: Int) {
        self.init(frame: frameRect)
        self.number = number
        layoutSubviews()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    func layoutSubviews() {
        let label = NSTextField(frame: NSMakeRect(0, 0, 60, 30))
        label.stringValue = "\(self.number!)"
        addSubview(label)
    }
}

Now, despite the fact that I am using an NSCollectionViewFlowLayout, conforming to the NSCollectionViewDelegateFlowLayout and providing a sizeForItemAt all indices, the resultant CollectionViewItemView is always sized 0, as shown below:

NSCollectionView

In sample projects online, the authors always feed an NSZeroRect to the frame of the NSCollectionViewItem. If I give it a custom NSRect, it always renders them on top of each other (since the origin of the frame is always the same).

What is the proper way of doing this? I'm at a loss. Why is the NSCollectionView not responding to the NSCollectionViewDelegateFlowLayout ?

4

1 回答 1

1

我从来没有见过这个问题,但这里有一个猜测:

CollectionViewItem你是压倒一切的loadView(),但它从不调用super.loadView(). CollectionViewItem是一个子类,NSViewController如果你重写loadView(),你必须首先调用super.loadView(),以便视图控制器可以初始化其内部状态。

如果您要以 macOS 10.10 及更高版本为目标,您可能希望改为覆盖viewDidLoad()

于 2018-01-08T23:41:57.903 回答