繁体   English   中英

设计UITableView / Cell-iOS

[英]Designing a UITableView/Cell - iOS

我正在设计一个使用子视图的UITableView来填充它的可重用单元格,我希望对此有一些看法。 如我所测试,它运作良好。 但是,我不知道这是否是一个好的解决方案。

场景是:我有一个具有不同类型的单元格(布局)的表格视图。 当我设计时,它增长很快(我的控制器代码),因为我必须注册很多单元并处理cellForRow。 然后,我想到了这个想法,即为一个唯一的可重用单元实例化不同的子视图,并使用“ Presenter”来处理委托/数据源。 您认为这是一个问题吗? 那是个好方法吗?

提前致谢!

诗:对您的英语错误表示歉意!

编辑:

这是项目中的会话,后跟解码: 捆绑图片

代码位于:

  • OrderDetailCell

     class OrderDetailCell: UITableViewCell { //MARK: Outlets @IBOutlet weak var cellHeight: NSLayoutConstraint! @IBOutlet weak var viewContent: UIView! //Variables var didUpdateLayout = false internal func setupLayoutWith(view: UIView){ cellHeight.constant = view.frame.height viewContent.frame = view.frame viewContent.addSubview(view) updateConstraints() layoutIfNeeded() didUpdateLayout = true } } 
  • OrderDetailSubview

     class OrderDetailSubview: UIView { var type: OrderDetailsSubViewType? var height: CGFloat = 1 class func instanceFromNib(withType type: OrderDetailsSubViewType) -> OrderDetailSubview { let view = UINib(nibName: type.rawValue, bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! OrderDetailSubview switch type { case .OrderDetailSubviewStatus: view.height = 258 case .OrderDetailSubViewItem: view.height = 129 case .OrderDetailSubViewStoreInformation: view.height = 317 case .OrderDetailSubViewEvaluation: view.height = 150 } view.updateConstraints() view.layoutIfNeeded() return view } } 
  • OrderDetailPresenter

     enum OrderDetailsSubViewType: String { case OrderDetailSubviewStatus = "OrderDetailSubviewStatus", OrderDetailSubViewItem = "OrderDetailSubViewItem", OrderDetailSubViewStoreInformation = "OrderDetailSubViewStoreInformation", OrderDetailSubViewEvaluation = "OrderDetailSubViewEvaluation" static let types = [OrderDetailSubviewStatus, OrderDetailSubViewItem, OrderDetailSubViewStoreInformation, OrderDetailSubViewEvaluation] } class OrderDetailPresenter { //Constants let numberOfSections = 4 //Variables // var order: Order? func setup(reusableCell: UITableViewCell, forRowInSection section: Int) -> OrderDetailCell { let cell = reusableCell as! OrderDetailCell for sub in cell.viewContent.subviews { sub.removeFromSuperview() } let subView = OrderDetailSubview.instanceFromNib(withType: OrderDetailsSubViewType.types[section]) cell.setupLayoutWith(view: subView) return cell } func numberOfRowsForSection(_ section: Int) -> Int { switch section { case 1: //TODO: count de offerList return 4 default: return 1 } } } 
  • OrderDetailViewController

     class OrderDetailViewController: BaseViewController { //MARK: Outlets @IBOutlet weak var tableView: UITableView! var presenter = OrderDetailPresenter() override func setupView() { setupTableView() } } extension OrderDetailViewController: UITableViewDataSource, UITableViewDelegate { internal func setupTableView() { tableView.delegate = self tableView.dataSource = self tableView.estimatedRowHeight = 600 tableView.rowHeight = UITableViewAutomaticDimension tableView.register(UINib(nibName: "OrderDetailCell", bundle: nil), forCellReuseIdentifier: "OrderDetailCell") } func numberOfSections(in tableView: UITableView) -> Int { return presenter.numberOfSections } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return presenter.numberOfRowsForSection(section) } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let reusableCell = tableView.dequeueReusableCell(withIdentifier: "OrderDetailCell") as! OrderDetailCell let cell = presenter.setup(reusableCell: reusableCell, forRowInSection: indexPath.section) return cell } } 

*很抱歉在这里缩进...

而已! 你认为呢?

在这里,您希望具有多个UITableViewCell子类,这些子类实现所需的不同布局,然后在表视图数据源中选择相关的布局。

class Cell1: UITableViewCell {

    let label = UILabel()

    override init(style: UITableViewCellStyle, reuseIdentifier: String) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.contentView.addSubview(label)
    }

    ... whatever other setup/layout you need to do in the class ...

}

class Cell2: UITableViewCell {

    let imageView = UIImageView()

    override init(style: UITableViewCellStyle, reuseIdentifier: String) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.contentView.addSubview(imageView)
    }

    ... whatever other setup/layout you need to do in the class ...

}

然后在您的视图控制器中

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(Cell1.self, forCellReuseIdentifier: "cell1Identifier")
    tableView.register(Cell2.self, forCellReuseIdentifier: "cell2Identifier")
}

...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row % 2 == 0 { // just alternating rows for example
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell1Identifier", for: indexPath) as! Cell1
        // set data on cell
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell2Identifier", for: indexPath) as! Cell2
        // set data on cell
        return cell
    }
}

因此,这只是一个示例,但是在表视图中使用两个不同的单元子类来交替行。

let dynamicCellID: String = "dynamicCellID" //One Cell ID for resuse
class dynamicCell: UITableViewCell {

    var sub: UIView // you just need to specify the subview

    init(sub: UIView) {
        self.sub = sub
        super.init(style: .default, reuseIdentifier: dynamicCellID)

        self.addSubview(sub)
        self.sub.frame = CGRect(x: 0, y: 0, width: sub.frame.width, height: sub.frame.height)
    }

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

}

而且您需要创建一个views数组,以便将该视图提供给委托中的每个单元格

let views: [UIView] = []

   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{

                    return views.count
    }

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

                    let v = views[indexPath.row]
                    return dynamicCell(sub: v)
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

                    let v = views[indexPath.row]
                    return v.frame.height + 10 //offset is 10 point
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM