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 个)调用的,为了简单起见我没有包括在这里
申请流程为:
- 申请开始
- 显示 TestTableViewController
然后有一些不同的选项供用户更新 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
就是这样!
我需要更新另一个 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 个)调用的,为了简单起见我没有包括在这里
申请流程为:
- 申请开始
- 显示 TestTableViewController
然后有一些不同的选项供用户更新 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
就是这样!