Невозможно добавить данные в массив из запроса GET

#ios #arrays #swift #xcode #alamofire

#iOS #массивы #swift #xcode #alamofire

Вопрос:

Я пытаюсь загрузить данные из запроса GET, используя библиотеку Alamofire в swift, и не могу добавить данные из запросов. Я пытаюсь заполнить массив заказов для загрузки в UITableView.

Я перепробовал несколько различных способов решения этой проблемы, но у меня ничего не работает. Я прокомментировал метод, который я пробовал, потому что при 2 отдельных вызовах fetchAll...Orders и втором вызове всегда перезаписывается первый, а затем в TableView загружаются недостающие элементы.

 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()
//        }

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

        fetchAllCocktailOrders { orders in
            self.orders.append(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)
        }
    }
 

На данный момент я получаю эту ошибку с приведенным выше кодом: Cannot convert value of type '[Order]?' to expected argument type 'Order' . Идеальным результатом этого кода является добавление данных, собранных из каждого запроса GET, к массиву заказов. Я проверил, что запросы GET работают и возвращают правильные данные. Пожалуйста, помогите :]

Ответ №1:

Вы объявили orders тип [Order] , и ваши методы выборки возвращают блоки компиляции [Order]? . Как вы можете видеть, вы не можете преобразовать значение типа [Order]? в ожидаемый тип аргумента Order при написании self.orders.append(orders) .

Чтобы исправить это, поставьте защиту unwrap в вызовах метода выборки.

 fetchAllBeerOrders { orders in
    guard let _orders = orders else { return }

    self.orders.append(_orders)
    self.tableView.reloadData()
}

fetchAllCocktailOrders { orders in
    guard let _orders = orders else { return }

    self.orders.append(_orders)
    self.tableView.reloadData()
}
 

Теперь у вас есть потенциальная утечка памяти в вашем коде. fetchAllBeerOrders и fetchAllCocktailOrders являются асинхронными методами с блоками компиляции. Вы не можете использовать строгую ссылку на self here . Используйте weak , чтобы избежать утечки памяти, например:

 fetchAllBeerOrders { [weak self] orders in
    guard let _orders = orders else { return }

    self?.orders.append(_orders)
    self?.tableView.reloadData()
}

fetchAllCocktailOrders { [weak self] orders in
    guard let _orders = orders else { return }

    self?.orders.append(_orders)
    self?.tableView.reloadData()
}