NSCollectionView 在同一点呈现所有 NSCollectionViewItems
NSCollectionView renders all NSCollectionViewItems at the same point
我正在尝试以编程方式创建一个简单的 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
?
我从来没有见过这个问题,但这是一个猜测:
在 CollectionViewItem
中你覆盖了 loadView()
但它从不调用 super.loadView()
。 CollectionViewItem
是 NSViewController
的子类,如果您覆盖 loadView()
,则必须首先调用 super.loadView()
,以便视图控制器可以初始化其内部状态。
如果您打算以 macOS 10.10 及更高版本为目标,您可能需要覆盖 viewDidLoad()
。
我正在尝试以编程方式创建一个简单的 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
?
我从来没有见过这个问题,但这是一个猜测:
在 CollectionViewItem
中你覆盖了 loadView()
但它从不调用 super.loadView()
。 CollectionViewItem
是 NSViewController
的子类,如果您覆盖 loadView()
,则必须首先调用 super.loadView()
,以便视图控制器可以初始化其内部状态。
如果您打算以 macOS 10.10 及更高版本为目标,您可能需要覆盖 viewDidLoad()
。