我的问题是下面这行:
let recentItemsVC = ItemsViewController(items: recentItems, cellDescriptor: {$0.cellDescriptor })
我知道
ItemsViewController
结束
cellDescriptor
,但我不能把我的头绕在
{$0.cellDescriptor}
就其本身而言。没有
filter
,
map
,
compactMap
滤波器
等等,打电话来了。
两个问题:
2。传递什么
{ $0.cellDescriptor }
这本身就意味着什么?
import UIKit
import PlaygroundSupport
struct Album {
var title: String
}
struct Artist {
var name: String
}
struct CellDescriptor {
let cellClass: UITableViewCell.Type
let reuseIdentifier: String
let configure: (UITableViewCell) -> ()
init<Cell: UITableViewCell>(reuseIdentifier: String, configure: @escaping (Cell) -> ()) {
self.cellClass = Cell.self
self.reuseIdentifier = reuseIdentifier
self.configure = { cell in
configure(cell as! Cell)
}
}
}
final class ItemsViewController<Item>: UITableViewController {
var items: [Item] = []
let cellDescriptor: (Item) -> CellDescriptor
var didSelect: (Item) -> () = { _ in }
var reuseIdentifiers: Set<String> = []
init(items: [Item], cellDescriptor: @escaping (Item) -> CellDescriptor) {
self.cellDescriptor = cellDescriptor
super.init(style: .plain)
self.items = items
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = items[indexPath.row]
didSelect(item)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = items[indexPath.row]
let descriptor = cellDescriptor(item)
if !reuseIdentifiers.contains(descriptor.reuseIdentifier) {
tableView.register(descriptor.cellClass, forCellReuseIdentifier: descriptor.reuseIdentifier)
reuseIdentifiers.insert(descriptor.reuseIdentifier)
}
let cell = tableView.dequeueReusableCell(withIdentifier: descriptor.reuseIdentifier, for: indexPath)
descriptor.configure(cell)
return cell
}
}
final class ArtistCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .value1, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
final class AlbumCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .value2, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let artists: [Artist] = [
Artist(name: "Prince"),
Artist(name: "Glen Hansard"),
Artist(name: "I Am Oak")
]
let albums: [Album] = [
Album(title: "Blue Lines"),
Album(title: "Oasem"),
Album(title: "Bon Iver")
]
enum RecentItem {
case artist(Artist)
case album(Album)
}
let recentItems: [RecentItem] = [
.artist(artists[0]),
.artist(artists[1]),
.album(albums[1])
]
extension Artist {
func configureCell(_ cell: ArtistCell) {
cell.textLabel?.text = name
}
}
extension Album {
func configureCell(_ cell: AlbumCell) {
cell.textLabel?.text = title
}
}
extension RecentItem {
var cellDescriptor: CellDescriptor {
switch self {
case .artist(let artist):
return CellDescriptor(reuseIdentifier: "artist", configure: artist.configureCell)
case .album(let album):
return CellDescriptor(reuseIdentifier: "album", configure: album.configureCell)
}
}
}
let recentItemsVC = ItemsViewController(items: recentItems, cellDescriptor: {$0.cellDescriptor })
let nc = UINavigationController(rootViewController: recentItemsVC)
nc.view.frame = CGRect(x: 0, y: 0, width: 200, height: 300)
PlaygroundPage.current.liveView = nc.view