【问题标题】:NSCollectionView renders all NSCollectionViewItems at the same pointNSCollectionView 在同一点呈现所有 NSCollectionViewItem
【发布时间】:2018-06-16 00:44:29
【问题描述】:

我正在尝试以编程方式创建一个简单的NSCollectionView。我在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)
    }
}

这是我设置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()
        }
    }
}

以下是我创建自定义NSView 以在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)
    }
}

现在,尽管我使用NSCollectionViewFlowLayout,符合NSCollectionViewDelegateFlowLayout 并提供sizeForItemAt 所有索引,但结果CollectionViewItemView 的大小始终为0,如下所示:

在在线示例项目中,作者总是将NSZeroRect 提供给NSCollectionViewItem 的框架。如果我给它一个自定义的NSRect,它总是将它们呈现在彼此之上(因为框架的原点总是相同的)。

这样做的正确方法是什么?我不知所措。为什么NSCollectionView 没有回复NSCollectionViewDelegateFlowLayout

【问题讨论】:

    标签: swift macos appkit nscollectionview nscollectionviewitem


    【解决方案1】:

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

    CollectionViewItem 中,您将覆盖loadView(),但它从不调用super.loadView()CollectionViewItemNSViewController 的子类,如果您覆盖 loadView(),您必须首先调用 super.loadView(),以便视图控制器可以初始化其内部状态。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-21
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多