在AppKit中的NSCollectionView與UIKit中的UICollectionView有著很多異同點。他們都能夠使用代理和數(shù)據(jù)源方法來構(gòu)建其中的每個Cell/Item笤休。但是對于要求簡單的需求帅霜,AppKit提供了不使用代理就可以實現(xiàn)的簡單方法谭梗。
我們先來看看通過代理方法實現(xiàn)的NSCollectionView荒勇,下面是一個純代碼實現(xiàn)的NSCollectionView
// CKCollectionView.swift
class CKCollectionView: NSView { // 這里自定義了一個View用來當(dāng)做容器
lazy var scrollView: NSScrollView = NSScrollView.init(frame: bounds)
lazy var collectionView: NSCollectionView = { // 這里就是我們的NSCollectionView
// 這里和UICollectionView中的設(shè)計一樣要糊,我們需要設(shè)定布局
let flowLayout = NSCollectionViewFlowLayout.init()
flowLayout.scrollDirection = .vertical // 設(shè)置排列方式
let collection = NSCollectionView.init()
collection.collectionViewLayout = flowLayout // 指定布局
collection.isSelectable = true // item是否可以點擊
collection.register(CKCollectionViewItem.self, forItemWithIdentifier: CKCollectionViewItem.identifier) // 注冊Item 和NSCollectionView類似
return collection
}()
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
setupSubviews()
}
required init?(coder decoder: NSCoder) {
super.init(coder: decoder)
setupSubviews()
}
func setupSubviews() -> Void {
// 設(shè)置代理
collectionView.delegate = self
collectionView.dataSource = self
/**
這里需要注意N取D朊恕!
scrollView是必要的技竟,collectionView必須屬于scrollView的子控件冰肴。否則
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem
這個方法不會執(zhí)行!
而之所以NSClipView使用再包一層是為了和IB中的層級保持一致榔组,這里具體功效我暫時不是很清楚熙尉,目前強行加上
*/
let clipView = NSClipView.init(frame: bounds)
clipView.documentView = collectionView;
scrollView.contentView = clipView;
addSubview(scrollView)
setupSubviewsConstraints() // 添加約束
}
func setupSubviewsConstraints() -> Void {
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: (scrollView.superview?.topAnchor)!),
scrollView.leftAnchor.constraint(equalTo: (scrollView.superview?.leftAnchor)!),
scrollView.rightAnchor.constraint(equalTo: (scrollView.superview?.rightAnchor)!),
scrollView.bottomAnchor.constraint(equalTo: (scrollView.superview?.bottomAnchor)!),
])
scrollView.needsLayout = true
// 使用約束的話 下面這句話是必須有的 否則會影響window,導(dǎo)致window不能用鼠標(biāo)改變大小
scrollView.translatesAutoresizingMaskIntoConstraints = false
}
}
extension CKCollectionView: NSCollectionViewDataSource, NSCollectionViewDelegate {
// 返回Item個數(shù)
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
/**
返回我們的Item搓扯。這里有一個注意點:
NSCollectionViewItem是繼承自NSViewController检痰。而在NSViewController的初始化方法中,默認(rèn)回去尋找同名的IB锨推,和UIViewController不同的是铅歼,在沒有IB的時候,我們直接使用NSViewController.init()是不會有任何問題的换可,因為loadView方法中會為我們創(chuàng)建默認(rèn)的view椎椰。但是NSViewController則不會,如果我們不手動實現(xiàn)loadView方法自己設(shè)置view的話沾鳄,view不會被創(chuàng)建慨飘。所以如果如果遇到控制臺說nib找不到的時候,可以重點看看是不是哪個控制器的view沒有賦值译荞。
*/
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: CKCollectionViewItem.identifier, for: indexPath)
return item
}
// 點擊方法
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
print("items select")
}
}
// NSCollectionView的布局方法
extension CKCollectionView: NSCollectionViewDelegateFlowLayout {
// 返回Item的size
func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
return NSSize.init(width: 80, height: 80)
}
}