I create a translator app using yandex translate API. I create singleton class.
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()
}
}
In viewController I create some func:
func getTranslate(text: String, lang: String) {
TranslatorManager.shared.getTranslate(text: text, lang: lang)
translate = TranslatorManager.shared.translation
self.translationLabel.text = self.translate?.text[0]
}
which I call when I click the button:
@IBAction func translateTapped(_ sender: UIButton) {
guard let text = originalText.text else { return }
getTranslate(text: text, lang: "en-ru")
}
In this case, the translation is displayed on the label only after the second pressing of the button. What am I doing wrong? Why does not it work correctly?
You are not properly dealing with the fact that the translation is being done asynchronously in the background. You need to refactor your 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()
}
}
Then update your getTranslate
to deal with the new completion handler:
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 = ""
}
}
}
}