代码之家  ›  专栏  ›  技术社区  ›  user1107173

Swift:将{$0.property}作为闭包传递

  •  -1
  • user1107173  · 技术社区  · 7 年前

    我的问题是下面这行:

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

    我知道 ItemsViewController 结束 cellDescriptor ,但我不能把我的头绕在 {$0.cellDescriptor} 就其本身而言。没有 filter , map , compactMap 滤波器 等等,打电话来了。

    两个问题:

    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 回复  |  直到 7 年前
        1
  •  1
  •   ielyamani    7 年前
    1. 阿法克 recentItems +1个
    2. {$0.cellDescriptor} 是个了结。它的签名是 @escaping (Item) -> CellDescriptor Item 并返回 CellDescriptor . 在这种情况下,对于 它将返回该元素的 cellDescriptor . 不管是艺术家还是专辑, 细胞描述符

      延长线{ var cellDescriptor:单元格描述符{ 自动切换{ 返回CellDescriptor(reuseIdentifier:“artist”,配置:artist.configureCell) 返回CellDescriptor(reuseIdentifier:“album”,configure:album.configureCell) } }

    它设置了 reuseIdentifier textLabel?.text 成为艺术家的名字或专辑的标题。

        2
  •  1
  •   freytag    7 年前

    就是这一行代码:

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

    ItemsViewController 一系列的 Item 项目 作为参数。以及 项目 cellDescriptor