首页 > 解决方案 > 在 Swift 中使用单例和解析 JSON

问题描述

我使用 yandex translate API 创建了一个翻译器应用程序。我创建单例类。

class TranslatorManager {
    static let shared = TranslatorManager()

    var translation: Translation?

    let key = "mykey here"
    let translateUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate"

    func getTranslate(text: String, lang: String) {
        guard let url = URL(string: translateUrl + "?key=\(key)&text=\(text)&lang=\(lang)&format=plain&options=1") else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"

        URLSession.shared.dataTask(with: request) { (data, response, error) in
            if error != nil {
                print(error!.localizedDescription)
            }

            guard let data = data else { return }

            do {
                let translation = try JSONDecoder().decode(Translation.self, from: data)
                DispatchQueue.main.async {
                    self.translation = translation
                }
            } catch {
                print(error)
            }
         }.resume()
    }
}

在 viewController 我创建了一些函数:

func getTranslate(text: String, lang: String) {
    TranslatorManager.shared.getTranslate(text: text, lang: lang)
    translate = TranslatorManager.shared.translation
    self.translationLabel.text = self.translate?.text[0]
}

当我点击按钮时我调用它:

@IBAction func translateTapped(_ sender: UIButton) {
    guard let text = originalText.text else { return }
    getTranslate(text: text, lang: "en-ru")
}

在这种情况下,翻译仅在第二次按下按钮后才会显示在标签上。我究竟做错了什么?为什么它不能正常工作?

标签: iosjsonswiftapisingleton

解决方案


您没有正确处理翻译在后台异步完成的事实。你需要重构你的TranslationManager.

let key = "mykey here"
let translateUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate"

class TranslatorManager {
    static let shared = TranslatorManager()

    func getTranslate(text: String, lang: String, completion: @escaping (Translation?) -> Void) {
        guard let url = URL(string: translateUrl + "?key=\(key)&text=\(text)&lang=\(lang)&format=plain&options=1") else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"

        URLSession.shared.dataTask(with: request) { (data, response, error) in
            if let error = error {
                print(error.localizedDescription)
                completion(nil)
                return
            }

            guard let data = data else {
                completion(nil)
                return
            }

            do {
                let translation = try JSONDecoder().decode(Translation.self, from: data)
                completion(translation)
            } catch {
                print(error)
                completion(nil)
            }
        }.resume()
    }
}

然后更新您getTranslate以处理新的完成处理程序:

func getTranslate(text: String, lang: String) {
    self.translationLabel.text = "Translating..."
    TranslatorManager.shared.getTranslate(text: text, lang: lang) { translation in
        DispatchQueue.main.async {
            if let translation = translation {
                self.translationLabel.text = self.translate.text[0]
            } else {
                // failed, act accordingly
                self.translationLabel.text = ""
            }
        }
    }
}

推荐阅读