Swift:将{$ 0.property}作为结束符

时间:2018-08-22 21:07:59

标签: swift generics

下面是游乐场代码。

我的问题是针对以下一行:

let recentItemsVC = ItemsViewController(items: recentItems, cellDescriptor: {$0.cellDescriptor })

我知道ItemsViewControllercellDescriptor采取了封闭措施,但是我无法绕过{$0.cellDescriptor}本身的含义。此处没有filtermapcompactMapfilter等名称。

两个问题:

1。游乐场表演(4次)。是什么意思?

enter image description here

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

2 个答案:

答案 0 :(得分:1)

那是代码行:

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

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

的属性

答案 1 :(得分:1)

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

    扩展名最近项{     var cellDescriptor:CellDescriptor {         切换自我{         案例。艺术家(艺术家):             返回CellDescriptor(reuseIdentifier:“ artist”,配置:artist.configureCell)         案例。专辑(让相册):             返回CellDescriptor(reuseIdentifier:“ album”,配置:album.configureCell)         }     } }

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