Как получить JSONData в DetailViewController?стриж - PullRequest
0 голосов
/ 04 июля 2019

У меня есть 2 контроллера: CollectionViewController и DetailViewControllerCollectionViewController я получил данные и получил coctails.Теперь я хочу получить coctails?.drinks?[indexPath.row] и передать DetailViewController, где мне нужно снова извлечь fetchRequest, но с другим API и новым URL.Но при загрузке DetailViewController метод networkDataService.fetchDrink(drinkName: drinkName) не работает.Что я не так сделал?

struct Coctail: Codable {
   let drinks: [Drink]?
}

struct Drink: Codable {
   let strDrink : String?
   let strDrinkThumb : URL?
}

class NetworkDataService {

let networkManager = NetworkManager.shared

func fetchCoctails(completion: @escaping (Coctail?) -> Void) {
    let url = "https://www.thecocktaildb.com/api/json/v1/1/filter.php?c=Cocktail"
    networkManager.fetchData(url: url, completion: completion)
}

func fetchDrink(drinkName: String, completion: @escaping (Coctail?) -> Void) {
    let url = "https://www.thecocktaildb.com/api/json/v1/1/search.php?s=\(drinkName)"
    networkManager.fetchData(url: url, completion: completion)
   }
}

class CollectionViewController: UICollectionViewController {

var coctails: Coctail?
let networkDataService = NetworkDataService()

override func viewDidLoad() {
    super.viewDidLoad()

    networkDataService.fetchCoctails() { (coctails) in
        self.coctails = coctails

        DispatchQueue.main.async {
            self.collectionView.reloadData()
        }
    }

}

// MARK: UICollectionViewDataSource

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return coctails?.drinks?.count ?? 0
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell

    let drink = coctails?.drinks?[indexPath.row]

    cell.config(drink: drink)

    return cell
}

// MARK: - Navigation

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    guard let indexPath = collectionView.indexPathsForSelectedItems?.first else { return }
    let drink = coctails?.drinks?[indexPath.row]

    let destination = segue.destination as! DetailViewController
    destination.drinkName = drink?.strDrink ?? ""
   }
}

class DetailViewController: UIViewController {

var drinkName = ""
var coctail: Coctail?
let networkDataService = NetworkDataService()

override func viewDidLoad() {
    super.viewDidLoad()

    networkDataService.fetchDrink(drinkName: drinkName) { (coctail) in
        self.coctail = coctail
    }
}

1 Ответ

2 голосов
/ 04 июля 2019

Если вы используете название напитка, как в strDrink, то проблема в том, что вы отправляете что-то вроде:

'57 Chevy с белым номерным знаком

Это означает, что URL будет выглядеть примерно так:

https://www.thecocktaildb.com/api/json/v1/1/search.php?s='57 Шевроле с белым номерным знаком

И не будет переведен в кодированный URLURL автоматически.

Проблема с этим подходом заключается в том, что вам необходимо url кодировать имя перед отправкой его в API.Что-то вроде:

networkDataService.fetchDrink(drinkName: drinkName.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)) { (coctail) in
    self.coctail = coctail
}

Таким образом, вы получите URL с чем-то вроде:

https://www.thecocktaildb.com/api/json/v1/1/search.php?s=%2757%20Chevy%20with%20a%20White%20License%20Plate

Ссылаясь на эту кодированную строку URL: Swift - кодирование URL

С другой стороны, ваш API возвращает идентификатор напитка, idDrink, который следует использовать для получения сведений вместо запуска поиска, а затем извлечения первогоконкретное имяЧто может случиться позже, так это то, что у вас может быть два Джека Дэниела с разными значениями, и вы всегда будете показывать первое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...