首页 > 解决方案 > 使用内部闭包时可能存在内存泄漏

问题描述

我想确保以下内容没有内存泄漏。现在,为了在使用网络调用时从我的代码中抛出错误以使其正常工作,我必须保留对我dispatchgroupfunction处理数据的引用。

   func myFunc(
               completion: @escaping (_ success: () throws -> Bool) -> Void) {

                let fG = DispatchGroup()
                let processLinks = self.processDownloadData
                requestDownloadLinks(fromURL: url) { result in
                    switch result {
                    case .success(let data):
                        processLinks(data, fG, stagingBundle, {_ in
                            switch result {
                            case .failure(let error):
                                completion({ throw error })
                            case .success:
                                completion({ return true })
                            }
                        })
                    case .failure(let error):
                        completion({ return true }) 
                    }
                }

在哪里processDownloadData

    func processDownloadData(
        data: ((urls: [(url: URL, language: String)], version: String)),
        dispatchGroup: DispatchGroup),
        completion: @escaping (_ success: () throws -> Bool) -> Void) {
//write data 
}

requestDownloadLinks

  final func requestDownloadLinks(
        fromURL url: URL,
        completion: ((Result<(urls: [(url: URL, language: String)],
        version: String), Error>) -> Void)?  = nil
    ) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            guard let self = self else {return}
            self.httpManager?.get(url: url) {result in
                switch result {
                case .failure(let error):
                    if let completion = completion {
                        completion(.failure(LokalisationError.network(originatingError: error)))
                    }
                case .success(let data):
                    do {
                        guard let data = data as? Data else {
                            if let completion = completion {
                                completion(.failure(LokalisationError.malformedDataFromServer))
                            }
                            return
                        }
                        let decoder = JSONDecoder()
                        let contents = try decoder.decode(EndPointResponse.self, from: data)
                        if let data = contents.data {
                            let urls = data.map { URL(string: $0.url) ?? URL(fileURLWithPath: "") }
                            let language = data.map { $0.language }
                            let urlsForLang = Array(zip(urls, language))
                            if let completion = completion {
                                completion(.success( (urlsForLang, contents.version) ))
                            }
                        }
                    } catch let error {
                        if let completion = completion {
                            completion(.failure(LokalisationError.network(originatingError: error)))
                        }

     }
                }
            }
        }
    }

现在通过这样做我会造成内存泄漏吗?当我创建对dispatchgroup和函数的引用时,我认为在 http 调用完成之前它们不会被释放。现在这没关系,因为它要么成功完成,要么出错。还是这会导致内存泄漏?

标签: swiftmemory-leaks

解决方案


您的 DispatchGroup 将一直completion()存在,直到完成为止,requestDownloadLinks除非您在其中做一些有趣的processDownloadData事情。您通过一个闭包块将它作为来自myFunc()to的引用传递,在requestDownloadLinks该闭包块中您调用processDownloadData将 DispatchGroup 传递给它。如果它没有被传递或作为参考保存在其中,那么您可能是安全的。确保使用 Instruments 分析您的应用程序并检查内存分配和僵尸。您还可以在调试器中检查内存占用。如果您多次调用 myfunc,您应该会看到内存稳步增加。


推荐阅读