操场代码如下。
我的问题是针对以下行:
let recentItemsVC = ItemsViewController(items: recentItems, cellDescriptor: {$0.cellDescriptor })
我知道ItemsViewController
需要一个闭包cellDescriptor
,但不能理解{$0.cellDescriptor}
它本身的含义。这里没有调用filter
, map
, compactMap
,filter
等。
两个问题:
1.游乐场表演(4次)。这意味着什么?
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