[英]Mutating Struct property with asynchronous function
I have the following Struct that I want to initialize, and then use its method query() to mutate its result property.我有以下要初始化的结构,然后使用它的方法 query() 来改变它的结果属性。
Query() sends and fetches JSON data, then decodes it to a String. Query() 发送并获取 JSON 数据,然后将其解码为字符串。 When I declare query() as a mutating function, I receive the error "Escaping closure captures mutating 'self' parameter" in my URLSession.
当我将 query() 声明为变异 function 时,我在我的 URLSession 中收到错误“转义闭包捕获变异 'self' 参数”。
What do I need to change?我需要改变什么?
The call:来电:
var translation = Translate(string: "hello", base: "en", target: "de", result: "")
translation.query()
let translated = translation.result
The struct:结构:
struct Translate {
let string: String, base: String, target: String
var result: String
mutating func query() {
let body: [String: String] = ["q": self.string, "source": self.base, "target": self.target]
let bodyData = try? JSONSerialization.data(withJSONObject: body)
guard let url = URL(string: "https://libretranslate.com/translate") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = bodyData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
DispatchQueue.main.async {
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
if responseJSON["translatedText"] != nil {
self.result = responseJSON["translatedText"] as! String
}
}
}
return
}
.resume()
}
}
There are many issues in the code.代码中有很多问题。
The most significant issue is that the URLRequest
is asynchronous.最重要的问题是
URLRequest
是异步的。 Even if no error occurred result
will be always empty.即使没有发生错误,
result
也将始终为空。
You have to add a completion handler – it fixes the errors you got by the way – and it's highly recommended to handle all errors .你必须添加一个完成处理程序——它修复了你顺便得到的错误——强烈建议处理所有错误。
Instead of JSONSerialization
the code uses JSONDe/Encoder
代码使用
JSONDe/Encoder
而不是JSONSerialization
struct Translation : Decodable { let translatedText : String }
struct Translate {
let string: String, base: String, target: String
func query(completion: @escaping (Result<String,Error>) -> Void) {
let body: [String: String] = ["q": self.string, "source": self.base, "target": self.target]
do {
let bodyData = try JSONEncoder().encode(body)
let url = URL(string: "https://libretranslate.com/translate")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = bodyData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error { completion(.failure(error)); return }
completion( Result{ try JSONDecoder().decode(Translation.self, from: data!).translatedText} )
}
.resume()
} catch {
completion(.failure(error))
}
}
}
let translation = Translate(string: "hello", base: "en", target: "de")
translation.query() { result in
DispatchQueue.main.async {
switch result {
case .success(let translated): print(translated)
case .failure(let error): print(error)
}
}
}
Both exclamation marks ( !
) are safe.两个感叹号 (
!
) 都是安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.