我在使用 Alamofire 快速从 GET 请求加载数据以将项目加载到
UITableView
时遇到问题。
我有两种方法
fetchAllBeerOrders
和fetchAllCocktailOrders
,它们都可以正常工作并获取正确的项目。我遇到的问题是在 viewWillAppear
方法中,我调用这两个 fetch 方法并重新加载 tableView。按照顺序,我只有 fetchAllCocktailOrders
方法中的项目加载到 tableView 中,并且我已经通过切换顺序并从 fetchAllBeerOrders
加载项目进行了验证。
class DrinkOrdersTableViewController: UITableViewController {
var orders: [Order] = []
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Current Orders"
}
override func viewWillAppear(_ animated: Bool) {
fetchAllBeerOrders { orders in
self.orders = orders!
//print("Beer fetch: ", self.orders)
self.tableView.reloadData()
}
fetchAllCocktailOrders { orders in
self.orders = orders!
//print("Cocktail fetch: ", self.orders)
self.tableView.reloadData()
}
}
private func fetchAllCocktailOrders(completion: @escaping([Order]?) -> Void) {
Alamofire.request("http://127.0.0.1:4000/orders", method: .get)
.validate()
.responseJSON { response in
guard response.result.isSuccess else { return completion(nil) }
guard let rawInventory = response.result.value as? [[String: Any]?] else { return completion(nil) }
let currentOrders = rawInventory.compactMap { ordersDict -> Order? in
guard let orderId = ordersDict!["id"] as? String,
let orderStatus = ordersDict!["status"] as? String,
var pizza = ordersDict!["cocktail"] as? [String: Any] else { return nil }
pizza["image"] = UIImage(named: pizza["image"] as! String)
return Order(
id: orderId,
pizza: Pizza(data: pizza),
status: OrderStatus(rawValue: orderStatus)!
)
}
completion(currentOrders)
}
}
private func fetchAllBeerOrders(completion: @escaping([Order]?) -> Void) {
Alamofire.request("http://127.0.0.1:4000/orders", method: .get)
.validate()
.responseJSON { response in
guard response.result.isSuccess else { return completion(nil) }
guard let rawInventory = response.result.value as? [[String: Any]?] else { return completion(nil) }
let currentOrders = rawInventory.compactMap { ordersDict -> Order? in
guard let orderId = ordersDict!["id"] as? String,
let orderStatus = ordersDict!["status"] as? String,
var pizza = ordersDict!["pizza"] as? [String: Any] else { return nil }
pizza["image"] = UIImage(named: pizza["image"] as! String)
return Order(
id: orderId,
pizza: Pizza(data: pizza),
status: OrderStatus(rawValue: orderStatus)!
)
}
completion(currentOrders)
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Debugging ROWS", orders.count)
return orders.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "order", for: indexPath)
let order = orders[indexPath.row]
cell.textLabel?.text = order.pizza.name
cell.imageView?.image = order.pizza.image
cell.detailTextLabel?.text = "$\(order.pizza.amount) - \(order.status.rawValue)"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "orderSegue", sender: orders[indexPath.row] as Order)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "orderSegue" {
guard let vc = segue.destination as? OrderViewController else { return }
vc.order = sender as? Order
}
}
}
我不确定是否需要将 GET 请求合并为单个请求,或者我的方法逻辑是否错误,但我需要 tableView 来加载来自
fetchAllBeerOrders
和 fetchAllCocktailOrders
的订单。请帮忙
就像Levi Yonder所说,你的第二个请求替换
order
的结果确实有问题,但他提供的答案并不是最优的。
您必须记住网络请求是异步的。这意味着
fetchAllCocktailOrders
可以在 fetchAllBeerOrders
请求完成之前完成。在这种情况下,会出现同样的问题:
fetchAllCocktailOrders
首先完成,将数据附加到订单
fetchAllBeerOrders
完成,用此请求的结果替换当前批次的数据。
fetchAllBeerOrders { orders in
self.orders.append(orders)
self.tableView.reloadData()
}
fetchAllCocktailOrders { orders in
self.orders.append(orders)
self.tableView.reloadData()
}
fetchAllCocktailOrders
替换了
orders
中最初获取的所有内容,而不是附加到。
因此
fetchAllBeerOrders
正在调用 viewWillAppear
,后者会填充
fetchAllBeerOrders
,然后
orders
会替换
fetchAllCocktailOrders
中的所有内容,而不是附加到
orders
中的所有内容。
要解决此问题,当您调用
orders
时,请在 fetchAllCocktailOrders
后面附加函数返回的内容,而不是替换:
orders
为了实现从两个 GET 请求加载数据的目标,我需要使用 override func viewWillAppear(_ animated: Bool) {
fetchAllBeerOrders { beerOrders in
self.orders = beerOrders!
//print("Beer fetch: ", self.orders)
self.tableView.reloadData()
}
fetchAllCocktailOrders { coctailOrders in
self.orders.append(coctailOrders)
//print("Cocktail fetch: ", self.orders)
self.tableView.reloadData()
}
}
.append(contentsOf: orders!)
将数据附加到订单数组。在 viewWillAppear 方法中,第二次调用
self.orders = orders!
将始终覆盖第一次调用
fetchCocktailOrders
的内容。显然我是一个敏捷的菜鸟!
fetchBeerOrders
这是正确的代码。