我非常小心地将任何强大的指针传递给vIEwcontroller.而且我可以将视图控制器解散掉并且回到演示控制器而没有任何问题.但是,即使调用了vIEwcontroller的deinit,也不会释放由vIEwcontroller创建的Web()对象实例.
我究竟做错了什么?
BTW:启动文件下载,报告进度并报告文件位置.但是,一旦文件下载完毕,该对象永远不会被释放.
vIEwController.swift
@IBAction func buttonTapped(_ sender: UIbutton) { //first create an instance of Web class (download helper) let web = Web(url: "https://www.Google.com.sa/images/branding/Googlelogo/2x/Googlelogo_color_120x44dp.png") // all call back closures have no reference to self web.downloadfile( finishedHandler: {fileLocation in print("file stored to \(fileLocation)")},progressHandler: {bytes,total in print("written \(bytes) out of \(total)")},errorHandler: {msg in print("error: \(msg)")} )}
我已经将Web()定义为NSObject,它符合URLSessionDownloadDelegate以利用委托事件方法(dIDFinishDownload / dIDWriteBytes等).
Web.swift
import UIKitclass Web : NSObject { var urlTodownload : String? // the following variables are references to closures passed to the object. var progressCallback : ((_ bytesWritten:Int64,_ totalExpectedBytes: Int64)->())? var finishedCallback : ((_ fileLocation: String)->())? static var instanceCount = 0 // keep track of number of instances created init(url: String) { Web.instanceCount += 1 urlTodownload = url print(" new instance of Web created. Total : \(Web.instanceCount)") } deinit { Web.instanceCount -= 1 print("Web instance deallocated. Remaining: \(Web.instanceCount)") }}
我将文件下载逻辑添加为同一文件的扩展名:
extension Web : URLSessionDownloadDelegate { func downloadfile( finishedHandler: @escaPing (_ fileLocation:String)->(),progressHandler: @escaPing (_ bytesWritten:Int64,_ totalBytes: Int64)->(),errorHandler: @escaPing (_ errorMsg:String)->()) { // we need to capture the closure because,these will // be called once the delegate methods are triggered self.progressCallback = progressHandler self.finishedCallback = finishedHandler if let url = URL(string: self.urlTodownload!) { let session = URLSession( configuration: .default,delegate: self,delegateQueue: nil) let task = session.downloadTask(with: url) task.resume() } } // MARK :- Delegate methods func urlSession(_ session: URLSession,downloadTask: URLSessionDownloadTask,dIDFinishDownloadingTo location: URL) { // call the closure if it still exists self.finishedCallback?(location.absoluteString) } func urlSession(_ session: URLSession,dIDWriteData bytesWritten: Int64,totalBytesWritten: Int64,totalBytesExpectedToWrite: Int64) { // report progress by calling captured closure,if exists self.progressCallback?(totalBytesWritten,totalBytesExpectedToWrite) }}解决方法 在我跟踪了这个问题后(使用Memory Graph DeBUGger),我在这段代码(Web类 – 下载文件方法)中找出问题的原因:
if let url = URL(string: self.urlTodownload!) { let session = URLSession( configuration: .default,delegateQueue: nil) let task = session.downloadTask(with: url) task.resume()}
实际上有一个与实例化URLSession相关的问题没有摆脱它;因此,你必须做一个 – 手动处理来解决它,调用finishTasksAndInvalidate()
将适合这样的问题:
if let url = URL(string: self.urlTodownload!) { let session = URLSession( configuration: .default,delegateQueue: nil) let task = session.downloadTask(with: url) task.resume() // here we go: session.finishTasksAndInvalIDate()}
为了确保它按预期工作,我建议在委托方法和Web类中的deinit中添加断点,你应该看到它按预期工作(委托方法可以工作,然后调用deinit).
此外:
如果您想了解有关如何使用Memory Graph DeBUGger的更多信息,可以查看:How to debug memory leaks when Leaks instrument does not show them?
总结以上是内存溢出为你收集整理的ios – 如何解决Swift 4中的内存循环URLSession.downloadTask?全部内容,希望文章能够帮你解决ios – 如何解决Swift 4中的内存循环URLSession.downloadTask?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)