Swift-使用 Alamofire 发出多个 GET 请求时出现问题

问题描述 投票:0回答:3

我在使用 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
的订单。请帮忙

ios arrays swift alamofire
3个回答
1
投票

就像Levi Yonder所说,你的第二个请求替换

order
的结果确实有问题,但他提供的答案并不是最优的。

您必须记住网络请求是异步的。这意味着

fetchAllCocktailOrders
可以在 fetchAllBeerOrders 请求完成之前完成
。在这种情况下,会出现同样的问题: 

    同时请求开火
  1. fetchAllCocktailOrders
     首先完成,将数据附加到订单
  2. fetchAllBeerOrders
     完成,用此请求的结果替换当前批次的数据。
解决方案:

fetchAllBeerOrders { orders in self.orders.append(orders) self.tableView.reloadData() } fetchAllCocktailOrders { orders in self.orders.append(orders) self.tableView.reloadData() }
    

0
投票
您遇到此问题的原因是

fetchAllCocktailOrders

 替换了 
orders
 中最初获取的所有内容,而不是附加到。
因此 
fetchAllBeerOrders

正在调用

viewWillAppear

,后者会填充 
fetchAllBeerOrders
,然后 
orders
 会替换 
fetchAllCocktailOrders
 中的所有内容,而不是附加到 
orders
 中的所有内容。
要解决此问题,当您调用 
orders

时,请在

fetchAllCocktailOrders

 后面附加函数返回的内容,而不是替换:
orders


0
投票

为了实现从两个 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

这是正确的代码。
    

© www.soinside.com 2019 - 2024. All rights reserved.