Swift 5:什么是“转义闭包捕获变异的‘自我’参数"以及如何修复它 [英] Swift 5 : What's 'Escaping closure captures mutating 'self' parameter' and how to fix it
问题描述
大家好,我正在尝试制作一个简单且可重用的 Swift 网络层
Hello guys I'm trying to make a simple and re-usable Swift Network Layer
也许这不是在视图中循环返回数据的最佳方法,但在我尝试获取返回的 Api 数据以在 SwiftUI 视图中循环后,我收到错误:
Maybe it's not the best way to loop returned data in view but after I tried to get the returned Api data to Loop it in SwiftUI view I'm getting error :
Escaping closure captures mutating 'self' parameter
而且不知道我在这节课中遗漏了什么地方或什么
And don't know where or what i missed in this lesson
这是文件的图片
ContentView.swift
ContentView.swift
struct ContentView: View {
var emptyDataArr: [CollectionItem] = []
init() {
ServiceLayer.request(router: Router.getSources) { (result: Result<[String : [CollectionItem]], Error>) in
switch result {
case .success(let data):
print(data)
self.emptyDataArr = data["custom_collections"]!
case .failure:
print(result)
}
}
}
var body: some View {
VStack (alignment: .leading) {
Text("No thing yet")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
ServiceLayer 类 ServiceLayer.swift
ServiceLayer Class ServiceLayer.swift
class ServiceLayer {
// 1.
class func request<T: Codable>(router: Router, completion: @escaping (Result<[String: [T]], Error>) -> ()) {
// 2.
var components = URLComponents()
components.scheme = router.scheme
components.host = router.host
components.path = router.path
components.queryItems = router.parameters
// 3.
guard let url = components.url else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = router.method
// 4.
let session = URLSession(configuration: .default)
let dataTask = session.dataTask(with: urlRequest) { data, response, error in
// 5.
guard error == nil else {
completion(.failure(error!))
print(error?.localizedDescription)
return
}
guard response != nil else {
return
}
guard let data = data else {
return
}
print(data)
// 6.
let responseObject = try! JSONDecoder().decode([String: [T]].self, from: data)
// 7.
DispatchQueue.main.async {
// 8.
completion(.success(responseObject))
}
}
dataTask.resume()
}
}
推荐答案
问题在于 ContentView
是一个结构体,这意味着它是一个值类型.你不能把它传递给一个闭包并改变它.如果你这样做了,什么都不会改变,因为闭包会有它自己独立的结构副本.
The problem is that ContentView
is a struct, which means it's a value type. You can't pass that to a closure and mutate it. If you did, nothing would change, because the closure would have its own independent copy of the struct.
您的问题是您混合了视图和模型.一个给定的 View 可以有很多很多的副本(每次它传递给一个函数时,都会制作一个副本).您不会希望这些副本中的每一个都发起请求.而是将这个请求逻辑移动到一个 Model 对象中,让 View 观察它.
Your problem is that you've mixed your View and your Model. There can be many, many copies of a given View (every time it's passed to a function, a copy is made). You wouldn't want every one of those copies to initiate a request. Instead move this request logic into a Model object and just let the View observe it.
这篇关于Swift 5:什么是“转义闭包捕获变异的‘自我’参数"以及如何修复它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!