因此,我将viewControllers嵌入viewControllers中以构建复杂的tableView(请参阅Dave Delong Better MVC文章https://davedelong.com/blog/2017/11/06/a-better-mvc-part-1-the-problems/)。我所有的tableView单元都是遵循以下CellVC协议的ViewController,并且它们在加载时作为子视图添加到UITableViewCell的contentView中。
此方法的优点是可以将单元的所有逻辑封装在嵌入式viewController中。具体来说,当选择单元格(didSelect),显示附件类型等时该怎么做。
如何让编译器知道如果对象采用CellVC,则它必须是UIViewController,这样我就不必将CellVC转换为UIViewController?
此协议因“ EXE_BAD_ACESS”而崩溃
import UIKit
protocol CellVC where Self: UIViewController {
var showDisclosureIcon: Bool { get }
func activateTF()
func didSelect()
}
此版本的协议有效,但没有告诉编译器,因为符合CellVC的类型是UIViewController。
protocol CellVC {
var showsDisclosureIcon: Bool { get }
func activateTF()
func didSelect()
}
实现-一个作为ViewController的“单元”之一的示例。
import UIKit
import CoreData
class ScheduleCell: UIViewController, CellVC {
//MARK: - Factory
static func create(context: NSManagedObjectContext) -> ScheduleCell {
let sB = UIStoryboard(name: "ScheduleCell", bundle: nil)
guard let cell = sB.instantiateViewController(withIdentifier: "ScheduleCell") as? ScheduleCell else {
fatalError("cell load failed")}
cell.context = context
return cell
}
//MARK: - Properties
var context: NSManagedObjectContext!
@IBOutlet var label: UILabel!
@IBOutlet var detailLabel: UILabel!
@IBOutlet var checkboxContainer: UIView!
//MARK: - CellVC
var showDisclosureIcon: Bool = true
func activateTF() { return } //No Text to Activate
func didSelect() {
let vc = UIViewController()
vc.view.backgroundColor = .purple
self.navigationController?.pushViewController(vc, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
setupLabels()
}
func setupLabels() {
label.text = "Schedule"
detailLabel.text = "Dunno"
}
}
消费-在这里您可以看到不受欢迎的向下转换“ cellVC as!UIViewController”和最后一行“ if cellVC.showsDisclosureIcon {...}”崩溃并显示为“ EXC_BAD_ACCESS”,这使我想到了编写协议的方式是错误的。
func configureCell(_ cell: UITableViewCell, at indexPath: IndexPath) {
let cellVC = data.cellVCForRowAt(indexPath: indexPath)
self.embed(viewController: cellVC as! UIViewController, inContainerView: cell.contentView)
if cellVC.showDisclosureIcon {
cell.accessoryType = .disclosureIndicator
}
}