我正在制作一个简单的演示程序。我想将选定的tableviewcell的产品数据发送到下一个ViewController(ProductDetailViewController)。
我认为直接访问另一个viewController的属性不值得考虑安全性,所以我制定了自定义协议并使用委托模式。
我的应用程序的rootViewController是ProductviewController,它是数据发送方对象。不幸的是,因为数据接收方对象“ProductDetailViewController”在ProductViewController.delegate?.didReceiveData(productList[indexPath.row])
代码执行时尚未加载,所以什么都没有发生。
ProductDetailViewController至少被导航加载一次后,数据发送工作,但一开始不工作,所以成功了一半。
这是我密码
这是ProductViewController(数据发送器对象):
import UIKit
final class ProductViewController: UIViewController {
static var delegate : ProductDetailViewDelegate?
private let productTableView = UITableView()
let productList : [Product] = [
Product(name: "1907 Wall Set", cellImageName: "image-cell1", fullscreenImageName: "phone-fullscreen1"),
Product(name: "1921 Dial Phone", cellImageName: "image-cell2", fullscreenImageName: "phone-fullscreen2"),
Product(name: "1937 Desk Set", cellImageName: "image-cell3", fullscreenImageName: "phone-fullscreen3"),
Product(name: "1984 Moto Portable", cellImageName: "image-cell4", fullscreenImageName: "phone-fullscreen4")
]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGray6
setTable()
setUI()
}
func setTable() {
productTableView.delegate = self
productTableView.dataSource = self
productTableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "Reused")
productTableView.rowHeight = 94
productTableView.backgroundColor = .systemGray6
let header = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 18))
productTableView.tableHeaderView = header
}
func setUI() {
productTableView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(productTableView)
NSLayoutConstraint.activate([
productTableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
productTableView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
productTableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
productTableView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor)
])
}
}
extension ProductViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Reused", for: indexPath) as! CustomTableViewCell
cell.productName.text = productList[indexPath.row].name ?? "nonamed"
cell.productImage.image = UIImage(named: productList[indexPath.row].cellImageName ?? "star")
return cell
}
}
extension ProductViewController : UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let nextVC = ProductDetailViewController()
ProductViewController.delegate?.didReceiveData(productList[indexPath.row])
self.navigationController?.pushViewController(nextVC, animated: true)
}
}
这是ProductDetailViewController(数据接收器对象)
import UIKit
protocol ProductDetailViewDelegate : AnyObject {
func didReceiveData(_ product : Product?)
}
final class ProductDetailViewController: UIViewController {
var currentProduct : Product?
override func viewDidLoad() {
super.viewDidLoad()
ProductViewController.delegate = self
}
}
extension ProductDetailViewController : ProductDetailViewDelegate {
func didReceiveData(_ product: Product?) {
currentProduct = product
}
}
1条答案
按热度按时间mwkjh3gx1#
您使用了不应该使用的委托模式。切勿使用委托模式直接转发数据。您的
ProductViewController
需要在创建ProductDetailViewController
时直接提供数据。由于ProductViewController
直接创建并显示ProductDetailViewController
,ProductViewController
可以直接将数据交给ProductDetailViewController
。不需要委托。不需要是静态的或单例的。您的
ProductDetailViewController
类变为:删除
ProductDetailViewDelegate
协议和相应的ProductDetailViewController
扩展。然后
ProductViewController
的didSelectRowAt
委托方法变为:同时删除
ProductViewController
中的静态delegate
属性。现在您的代码更简单、更清晰。以
UITableView
为例,了解何时需要使用委托模式。许多不同的东西都可以创建表视图。表视图并不确切知道是什么创建了它。委托模式允许表视图在需要时请求其创建者(或任何其他被设置为其委托的对象)提供数据,并允许表视图通知其创建者有关事件的信息。在您的例子中,
ProductDetailViewController
不需要向任何人请求数据,也不需要通知任何人任何事件。它的创建者可以在创建时将其初始数据传递给它,然后结束通信。如果您稍后扩展
ProductDetailViewController
,使其确实需要一个委托模式来与其创建者进行通信,那么您需要修复您最初的尝试。ProductDetailViewDelegate
协议。delegate
属性添加到ProductDetailViewController
,而不是ProductViewController
。ProductViewController
添加实现ProductDetailViewDelegate
的扩展。ProductViewController
创建ProductDetailViewController
时,细节控制器的delegate
属性设置为self
。ProductDetailViewDelegate
调用其delegate
上的委托方法来获取数据或通知它事件。