Swift 5:什么是“转义闭包捕获变异的‘自我’参数"以及如何修复它 [英] Swift 5 : What's 'Escaping closure captures mutating 'self' parameter' and how to fix it

查看:54
本文介绍了Swift 5:什么是“转义闭包捕获变异的‘自我’参数"以及如何修复它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我正在尝试制作一个简单且可重用的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆