一般我们很多地方用到列表。那么为了优雅

就可以单独抽出来

//
// CommonList.swift
// geekTimeSwiftUI
//
// Created by Ben Lv on 2020/2/8.
// Copyright © 2020 ruibo. All rights reserved.
//




import Foundation
import UIKit


class CommonListCell<ItemType>: UITableViewCell {
var item: ItemType?
required override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

protocol CommonListDelegate:AnyObject {
func didSelectItem<Item>(_ item: Item)
}


class CommonList<ItemType,CellType:CommonListCell<ItemType>>: UIView,UITableViewDataSource,UITableViewDelegate {

var tableView: UITableView
var items: [ItemType]! = []{
didSet {
self.tableView.reloadData()

}
}

weak var delegate: CommonListDelegate?

override init(frame: CGRect) {
tableView = UITableView(frame: .zero, style: .plain)
// items = []
super.init(frame: frame)
self.setupView()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func setupView() {
tableView.dataSource = self
tableView.delegate = self
tableView.tableFooterView = UIView()
self.addSubview(tableView)
tableView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:CellType? = tableView.dequeueReusableCell(withIdentifier: "cellId") as? CellType
if cell == nil {
cell = CellType(style: .subtitle, reuseIdentifier: "cellId")
}
cell?.item = items[indexPath.row]
return cell!
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 120.0
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.didSelectItem(items[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
}

修改上篇的博客的代码

//
// ProductList.swift
// geekTimeSwiftUI
//
// Created by Ben Lv on 2020/1/31.
// Copyright © 2020 ruibo. All rights reserved.
//

import Foundation
import UIKit


class ProductCell: CommonListCell<Product> {

let priceLabel: UILabel
let productImageView: UIImageView

override var item: Product? {
didSet{
if let p = self.item {
self.productImageView.kf.setImage(with: URL(string: p.imageUrl))
self.textLabel?.text = p.name
self.detailTextLabel?.text = p.desc
self.priceLabel.text = "$\(p.price)"
}
}
}

required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
priceLabel = UILabel(frame: .zero)
productImageView = UIImageView()
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.setupView()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func setupView() {
textLabel?.textColor = UIColor.hexColor(0x333333)
detailTextLabel?.textColor = UIColor.hexColor(0x999999)
detailTextLabel?.numberOfLines = 2
priceLabel.textColor = UIColor.hexColor(0xe23b41)
priceLabel.font = UIFont.systemFont(ofSize: 15)
productImageView.contentMode = .scaleAspectFill
productImageView.clipsToBounds = true
contentView.addSubview(priceLabel)
contentView.addSubview(productImageView)


productImageView.snp.makeConstraints { (make) in
make.left.equalTo(contentView).offset(20)
make.top.equalTo(contentView).offset(10)
make.width.equalTo(80)
make.height.equalTo(100)
}

textLabel?.snp.makeConstraints({ (make) in
make.left.equalTo(productImageView.snp_right).offset(12)
make.top.equalTo(productImageView)
make.right.equalTo(contentView).offset(-20)
})

priceLabel.snp.makeConstraints { (make) in
make.left.equalTo(textLabel!)
make.centerY.equalTo(contentView)
}

detailTextLabel?.snp.makeConstraints({ (make) in
make.left.equalTo(textLabel!)
make.bottom.equalTo(productImageView)
make.right.equalTo(contentView).offset(-20)
})




}



}
//
// HomeViewController.swift
// geekTimeSwiftUI
//
// Created by Ben Lv on 2020/1/29.
// Copyright © 2020 ruibo. All rights reserved.
//

import UIKit
import Kingfisher
import SnapKit
class HomeViewController: BaseViewController,BannerViewDataSource,CommonListDelegate {
func didSelectItem<Item>(_ item: Item) {
if let product = item as? Product{
let detailVC = DetailViewController()
detailVC.product = product
detailVC.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(detailVC, animated: true)
}
}



override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
hidesBottomBarWhenPushed = false
}

func numberOfBanners(_ bannerView: BannerView) -> Int {
return FakeData.createBanners().count
}

func viewForBanner(_ bannerView: BannerView, index: Int, convertView: UIView?) -> UIView {
if let view = convertView as? UIImageView {
view.kf.setImage(with: URL(string: FakeData.createBanners()[index]))
return view
}else {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.kf.setImage(with: URL(string: FakeData.createBanners()[index]))
return imageView

}
}


override func viewDidLoad() {
super.viewDidLoad()
self.title = "Home"

let bannerView = BannerView(frame: CGRect(x:0,y:0,width: UIScreen.main.bounds.width,height: 176))
bannerView.autoScrollInterval = 2
bannerView.isInfinite = true
bannerView.dataSource = self
view.addSubview(bannerView)

let productList = CommonList<Product,ProductCell>(frame: .zero)
productList.delegate = self
productList.items = FakeData.createProducts()
view.addSubview(productList)
productList.snp.makeConstraints { (make) in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(bannerView.snp_bottom).offset(5)
}


}




}

对比之下。简洁了很多