-1

操场代码如下。

我的问题是针对以下行:

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
4

2 回答 2

1

就是那行代码:

    init(items: [Item], cellDescriptor: @escaping (Item) -> CellDescriptor) {

ItemsViewController您使用数组Item和回调方法初始化。回调方法接受一个Item作为参数。并且Item有一个名为cellDescriptor

于 2018-08-22T21:13:16.217 回答
1
  1. AFAIK 4 次recentItems+ 1的计数
  2. {$0.cellDescriptor}是一个闭包。它的签名是@escaping (Item) -> CellDescriptor. 这意味着它需要一个泛型类型Item并返回一个CellDescriptor. 在这种情况下,它的每个元素都recentItems将返回该元素的cellDescriptor. 无论是艺术家还是专辑,cellDescriptor都是由这部分代码定义的:

    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" , 配置:album.configureCell) } } }

它通过设置为艺术家的姓名或专辑的标题来reuseIdentifier设置和配置单元格。textLabel?.text

于 2018-08-23T00:07:58.523 回答