Swift 使用委托表视图刷新另一个 class 的内容

Swift using delegate tableview to refresh content from another class

我需要更新另一个 class 的 TableView 的内容,该 class 执行对外部 API 的异步调用。

我实现了一个在 API 调用后刷新 table 的协议,但似乎此代码从未执行过。 我不明白我的代码有什么问题。可能我忘记了什么,这是我的第一个应用程序,我刚刚开始研究协议实现

下面我写了一个代码示例,其中我删除了所有不必要的代码(对于这个问题)。

协议定义:

protocol ProductUpdateDelegate: class {
        func refreshTableView()
    }

Tabelview 实现:

    class TestTableViewController: UITableViewController,
UITextFieldDelegate, ProductUpdateDelegate {

    var productList = [productInfo]()

    // Delegate function implementation
        func refreshTableView() {
              self.tableView.reloadData()
              self.tableView.beginUpdates()
              self.tableView.endUpdates()
        }

        override func viewDidLoad() {
          super.viewDidLoad()
          self.tableView.rowHeight = 50;
          self.tableView.dataSource = self
          self.tableView.delegate = self
          more code ...
        }

   @IBAction private func buttonTappedAction(_ sender: Any) {

    code that get input from user and did some check...

    if(isValidCode){
     self.storeProduct(productCode: code)        
    }

 }


func storeProduct(productCode: String){
        if(isNewCode){
          self.productList.append(productInfo(code: productCode,
          quantity: 1))

                }

         more code ...

        }

Class 需要更新 tableView

上的一些信息
import Foundation

class Product {

   weak var delegate: ProductUpdateDelegate?

   some code here...

   func getProductInfoFromAPI(){

     API CAll...

     if(result != "no_data")
      self.delegate?.refreshTableView()
     }

     more code ...

}

class 用于存储有关产品的信息并用于使用远程更新产品描述 API

import Foundation

class productInfo: NSObject, NSCoding, Codable {

    var code = ""
    var quantity = 1
    public var product_name = "Wait for information..."

    init(code: String, quantity : Int, 
product_name : String = "Wait for information...") {
        self.code = code
        self.quantity = quantity
        self.product_name = product_name
        super.init()
        self.getProductInfoFromAPI()
    }

    required convenience init(coder aDecoder: NSCoder) {
        let code = aDecoder.decodeObject(forKey: "code") as! String
        let quantity = aDecoder.decodeInteger(forKey: "quantity")
        self.init(code:code, quantity:quantity)
        self.getProductInfoFromAPI()
    }

    func getProductInfoFromAPI(){
        let productInfo = Product()
        productInfo.getInfoByCode(productCode: code, refObject: self)
    }


    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.code, forKey: "code")
        aCoder.encode(self.quantity, forKey: "quantity")
    }
}

UPDATE1: 产品 class 是从其他一些 classes(总共 4 个)调用的,为了简单起见我没有包括在这里

申请流程为:

然后有一些不同的选项供用户更新 TableView 内容,每个选项由单独的 class 控制,因此产品 class 是从其他 class 调用的es 并且是唯一一个直接与 TestTableViewController

交互的

更新2: 添加更多代码以显示完整过程。 视图初始化后,用户可以单击按钮并插入产品代码。

插入的代码使用append保存在productInfo数组中。此操作激活 productInfo 的 init 方法 class 并开始调用远程服务以检索有关产品本身的信息。

问题是文章信息更新正确但没有显示在table视图中,因为视图未更新。 因为是一个异步进程,所以我需要一种方法来在检索过程完成后更新视图内容。 所以我认为最好的解决方案是协议。但如前所述,函数 refreshTableView 似乎被忽略了。

var refreshControl = UIRefreshControl()

@IBOutlet weak var tblView: UITableView!


override func viewDidLoad() {
    super.viewDidLoad()
    refreshControl.attributedTitle = NSAttributedString(string: "")
    refreshControl.addTarget(self, action: #selector(refresh(sender:)), for: UIControl.Event.valueChanged)
    tblView.addSubview(refreshControl)
}


@objc func refresh(sender:AnyObject) {
    refreshControl.endRefreshing()
    apiFunction()
}


func apiFunction(){
    // call your api
}

根据您的代码,您没有为 Product class 中名为 delegate 的弱变量设置任何值。您应该将它设置为 class 谁应该使用它。 一种方法是使您的 Product class 成为单例,并且只初始化一次。 例如

class Product {
   static let shared = Product()
   weak var delegate: ProductUpdateDelegate?

   private init() { }

   func getProductInfoFromAPI(){
     if(result != "no_data")
     self.delegate?.refreshTableView()
   }
}

在你的 tableview controller 而不是 let productInfo = Product() 你可以使用 let productInfo = Product.shared 然后设置你的委托。

productInfo.delegate = self

就是这样!