【发布时间】:2017-08-21 19:43:43
【问题描述】:
我有一个应用程序(部分)向用户显示 Wi-Fi 连接的当前下载速度。它通过打开一个URLSession 并下载一个中等大小 (~10MB) 的文件并测量它所花费的时间来做到这一点。
这是 URLSession 函数:
func testSpeed() {
Globals.shared.dlStartTime = Date()
Globals.shared.DownComplete = false
if Globals.shared.currentSSID == "" {
Globals.shared.bandwidth = 0
Globals.shared.DownComplete = true
} else {
let url = URL(string: [HIDDEN])
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: url!)
task.resume()
}
}
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
Globals.shared.dlFileSize = (Double(totalBytesExpectedToWrite) * 8) / 1000
let progress = (Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)) * 100.0
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ProcessUpdating"), object: nil, userInfo: ["progress" : progress])
}
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
let elapsed = Double( Date().timeIntervalSince(Globals.shared.dlStartTime))
Globals.shared.bandwidth = Int(Globals.shared.dlFileSize / elapsed)
Globals.shared.DownComplete = true
Globals.shared.dataUse! += (Globals.shared.dlFileSize! / 8000)
session.invalidateAndCancel()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ProcessFinished"), object: nil, userInfo: nil)
}
正如您可能从委托函数中看出的那样,这一切都存在于与视图控制器分开的类中,以及其他一些小型网络功能,例如获取 IP 和 SSID。代表发布视图控制器观察到的通知。
我的 ViewController 有一个 NSTimer,它每 5 秒回调一次此 URLSession 以重新测试速度(但只有在前一个完成时才运行它)。这是代码:
reloadTimer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(rescanNetwork), userInfo: nil, repeats: true)
调用这个函数:
func backgroundRescan() {
if Globals.shared.DownComplete {
Networking().testSpeed()
}
}
它再次运行 URL Session,当然要检查以确保前一个已经完成。
由于某种原因,我在测试中使用了大量内存,直到应用程序达到 2GB 的内存使用并被控制台输出 Message from debugger: Terminated due to memory issue 终止。这一切都发生在运行应用程序的两分钟内。
我什至在完成委托中添加了session.invalidateAndCancel(),以拼命尝试清除该记忆。但它没有用。我错过了什么吗?
【问题讨论】:
-
您确定 Globals.shared.currentSSID 设置为 "" 以外的值吗?如果没有,您将每 5 秒添加一个进程,直到您炸毁为止。
-
您是否在某处对这些代表进行了强有力的参考?班级是什么样的?
-
不要每次都实例化一个新的 URLSession。这是 URLSession 的一个已知问题。
-
Mozahler:这不是真的。除非找到有效的 SSID,否则根本不会调用 URLSession; IE。您实际上已连接到本地网络。尝试和测试,没有问题。 Ssswift:没有强引用。 @Rob 还有其他选择吗?我可以告诉现有会话重新下载相同的文件吗?
-
纠正我自己,
URLSession问题出现在您重复实例化但从不使其无效的情况下。但是您正在使其无效,因此这不太可能是问题所在。此外,URLSession泄漏问题是以 kb 为单位衡量的,因此它不太可能是 gb 内存消耗的来源。它一定是别的东西。我会在 Xcode 8 中使用“调试内存图”功能并查找您认为应该释放但没有释放的对象,它会告诉您强引用在哪里(参见 stackoverflow.com/a/30993476/1271826)。
标签: swift xcode memory-management memory-leaks nsurl