【问题标题】:Dependency injection in uitableviewcell nibsuitableviewcell nib 中的依赖注入
【发布时间】:2017-01-01 08:17:50
【问题描述】:

我正在尝试构建一个非常复杂的表。此表的一个单元格导入另一个表。在这个导入的表中,我根据情况显示不同的行。导入的表格和所有可导入的表格单元都组织成自己的 nib 文件,每个单元都有自己的控制器。作为一名优秀的程序员,我正在尝试在整个项目中使用依赖注入。现在的问题是,当我使用通常的方式在 viewDidLoad() 中注册笔尖时

let cellNib = UINib(nibName: "BatchConsumptionCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionCell")

然后在 tableView(tableView: cellForRowAt:) 中将它们用作 dequeueReusableCell(withIdentifier: for:)

let batchConsumptionCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionCell", for: indexPath) as! BatchConsumptionCell
batchConsumptionCell.setConsumption(consumption: consumption)
return batchConsumptionCell

我无法及时注入依赖。

在 BatchConsumptionCell 中,我在 tableView(tableView: cellForRowAt:) 中所做的一切工作正常。该函数在 dequeueReusableCell(withIdentifier: for:) 执行后被调用。但是,一旦我尝试使 tableView(tableView: numberOfRowsInSection:) 动态化,我就会遇到问题。这个函数似乎是在 dequeueReusableCell(withIdentifier: for:) 之前调用的,所以此时没有注入依赖项。

我试图在我的 BatchConsumptionCell 中覆盖 init(nibName: bundle:) 初始化程序,但这是一个 UITableViewCell,所以我无法覆盖它。

我该如何处理?有什么方法可以在初始化 nib 及其控制器时注入依赖项?还是我组织我的细胞都错了?任何想法将不胜感激。

为了更清楚,这里是我的代码:

ConsumptionDetailViewController

import UIKit

class ConsumptionDetailViewController: UITableViewController {

// MARK: - Properties

var moc: NSManagedObjectContext!

var consumption: Consumption!


// MARK: - Outlet Properties

@IBOutlet weak var labelDate: UILabel!
@IBOutlet weak var labelTime: UILabel!
...


// MARK: - Default Methods

override func viewDidLoad() {
    super.viewDidLoad()

    let cellNib = UINib(nibName: "BatchConsumptionCell", bundle: nil)
    tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionCell")

    updateTableFields(selectedConsumption: consumption)
}


// MARK: - UI Update Methods

func updateTableFields(selectedConsumption: Consumption) {

    labelId.text = selectedConsumption.wtId
    ...
}

// MARK: - BatchAddEditDelegate Methods

func didFinishEditing(consumption: Consumption) {
    updateTableFields(selectedConsumption: consumption)
}

// MARK: - TableView Methods

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    ...
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    ...
}

override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    ...
}

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

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 1 && indexPath.row == 0 {
        let batchConsumptionCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionCell", for: indexPath) as! BatchConsumptionCell
        batchConsumptionCell.setConsumption(consumption: consumption)
        return batchConsumptionCell
    }
    return super.tableView(tableView, cellForRowAt: indexPath)
}


// MARK: - Navigation

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    ...
}

}

BatchConsumptionCell

import UIKit

class BatchConsumptionCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {

var consumption: Consumption!
var batchConsumptionCount: Int!

@IBOutlet weak var tableView: UITableView!

override func awakeFromNib() {
    super.awakeFromNib()

    var cellNib = UINib(nibName: "BatchConsumptionBasicCell", bundle: nil)
    tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionBasicCell")

    cellNib = UINib(nibName: "BatchConsumptionMultiCell", bundle: nil)
    tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionMultiCell")

    self.tableView.delegate = self
    self.tableView.dataSource = self
}

func setConsumption(consumption: Consumption) {
    self.consumption = consumption
    self.batchConsumptionCount = consumption.batchConsumptions?.count
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if batchConsumptionCount == 1 { // <-- This does not work
        return 3
    } else {
        return batchConsumptionCount
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if batchConsumptionCount == 1 { // <-- This works fine
        let batchConsumptionBasicCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionBasicCell", for: indexPath) as! BatchConsumptionBasicCell
        let bc = consumption.batchConsumptions?.allObjects[0] as! BatchConsumption
        if indexPath.row == 0 {
            batchConsumptionBasicCell.configure(title: "Batch", detail: (bc.batch?.wtId)!)
        } else if indexPath.row == 1 {
            batchConsumptionBasicCell.configure(title: "Weight", detail: String(describing: bc.weight!))
        } else if indexPath.row == 2 {
            batchConsumptionBasicCell.configure(title: "Price", detail: String(format:"%.2f", bc.price))
        }
    } else if batchConsumptionCount >= 2 {
        let batchConsumptionMultiCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionMultiCell", for: indexPath) as! BatchConsumptionMultiCell
        return batchConsumptionMultiCell
    }
    return UITableViewCell()
}

}

见 cmets // &lt;-- This works fine
// &lt;-- This does not work 在 BatchConsumptionCell 中

【问题讨论】:

  • 显示setConsumumption的代码
  • 还有在哪里更新 batchConsumptionCount 值?
  • 抱歉,忘记了 BatchConsumptionCell 中的 setConsumption(consumption:)

标签: ios swift uitableview dependency-injection swift3


【解决方案1】:

您还应该将 nib 注册到 BatchConsumptionCell 类,并实现必要的 table view 的数据源和委托方法:

class BatchConsumptionCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    var consumption: Consumption!
    var batchConsumptionCount: Int!

    override func awakeFromNib() {
        super.awakeFromNib()

        var cellNib = UINib(nibName: "BatchConsumptionBasicCell", bundle: nil)
        tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionBasicCell")

        cellNib = UINib(nibName: "BatchConsumptionMultiCell", bundle: nil)
        tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionMultiCell")

        self.tableView.delegate = self
        self.tableView.dataSource = self
    }

    func setConsumption(consumption: Consumption) {
        self.consumption = consumption
        self.batchConsumptionCount = consumption.batchConsumptions?.count
        tableView.reloadData()
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return consumption == nil ? 0 : 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if batchConsumptionCount == .some(1) { return 3 }
        return batchConsumptionCount ?? 0
    }

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

        switch batchConsumptionCount {
        case .some(1):
            let batchConsumptionBasicCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionBasicCell", for: indexPath) as! BatchConsumptionBasicCell
            let bc = consumption.batchConsumptions?.allObjects[0] as! BatchConsumption
            if indexPath.row == 0 {
                batchConsumptionBasicCell.configure(title: "Batch", detail: (bc.batch?.wtId)!)
            } else if indexPath.row == 1 {
                batchConsumptionBasicCell.configure(title: "Weight", detail: String(describing: bc.weight!))
            } else if indexPath.row == 2 {
                batchConsumptionBasicCell.configure(title: "Price", detail: String(format:"%.2f", bc.price))
            }
            return batchConsumptionBasicCell

        default:
            let batchConsumptionMultiCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionMultiCell", for: indexPath) as! BatchConsumptionMultiCell
            return batchConsumptionMultiCell

        }
    }

}

【讨论】:

  • 我已经做到了。 BatchConsumptionCell 看起来和你建议的差不多。标题是class BatchConsumptionCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate,我完全按照您使用let nib = UINib(...tableView.register(... 的方式加载单元格,但是我在哪里将我的依赖项注入到这个BatchConsumptionCell 中???
  • “注入我的依赖项”是什么意思?您能否将整个 BatchConsumptionCell 代码粘贴到您的问题上?
  • 在我的 BatchConsumptionCell 中,我需要 var consumption。目前,我在用dequeueReusableCell(withIdentifier: for:) 加载它之后通过batchConsumptionCell.setConsumption(consumption: consumption) 设置了这个变量(见上文)。但是,当我尝试根据tableView(tableView: numberOfRowsInSection:) 中的注入变量设置行数时,出现错误。 tableView(tableView: numberOfRowsInSection:) 似乎在我可以设置我的 consumption var 之前被调用。
  • 我更新了问题以获取更多详细信息。顺便说一句,非常感谢您的帮助 bubuxu ?
  • Ueee,用var consumption: Consumption! { didSet { batchConsumptionCount = consumption.batchConsumptions?.count tableView.reloadData() } } 重新加载整个表数据就成功了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 2014-06-12
  • 2013-04-10
  • 2010-11-27
相关资源
最近更新 更多