Swift 4 Перенос результатов в основной поток при использовании внешней сетевой инфраструктуры - PullRequest
0 голосов
/ 31 октября 2018

Я хотел получить данные с сервера API. Проблема в том, что все сетевые платформы делают это Async. Поэтому у меня есть проблемы, которые возвращают переменную, возвращают пустое. Вот мой код

Контроллер вида, где я вызываю функцию

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let url = "http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=12693365&apikey=63ee7da5e2ee269067ecc42b25590922"

        let musixrequest = MusicMatchRequest()
        let endResults =  musixrequest.gettingLyrics(url: url)
        if !endResults.isEmpty{
            print("The end results are \(endResults)")
        }else{
            print("No results found")
        }


    }

Вот мой класс, где я пытаюсь получить данные

public class MusicMatchRequest : NSObject{

public override init(){}

 public func gettingLyrics(url : String) -> String {

    var endResults = ""

    DefaultProvider.request(Route(path:"\(url)")).responseJSON { (response:Response<Any>) in
        switch response.result{
        case .success(let json):
         endResults = String(describing:json)
            print(endResults)
          case .failure(let error):
            print("error: \(error)")
            }
        }
        return endResults
    }


}

Когда я печатаю endRsults из задачи, с которой она работает, она печатает результаты, но var endResults возвращается пустой. Идея, как передать данные.

Я пробовал две рамки

  1. Alamofire

  2. Nikka

В обеих системах он действует одинаково.

1 Ответ

0 голосов
/ 31 октября 2018

Решение Я точно не знаю, что происходит под капотом, но в ЛЮБОЙ сетевой операции это также должно быть асинхронным (то есть, для извлечения данных потребуется определенное время).

let endResults = musixrequest.gettingLyrics(url: url)

Если это выполняется синхронно в главном потоке, он заблокирует его, поэтому пользователь не сможет взаимодействовать с приложением, что довольно плохо. Поскольку в вашем коде он асинхронный, вы сразу же читаете значение в следующей строке, здесь:

if !endResults.isEmpty {
    print("The end results are \(endResults)")
} else {
    print("No results found")
}

Маловероятно, что работа сети завершится за один шаг строки, поэтому у вас там не будет данных. Что вы должны сделать, это передать обработчик завершения в этом методе:

public func gettingLyrics(url : String) -> String

и отправить в основную ветку следующим образом:

DispatchQueue.main.async { // do you UI stuff here }

Измените свою функцию следующим образом:

public func gettingLyrics(url : String, completionHandler: (String) -> Void)

и вызов обработчика завершения в ветке успеха:

completionHandler(String(describing:json))

...