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