gpt4 book ai didi

ios - Swift Calendar.current 内存泄漏?

转载 作者:搜寻专家 更新时间:2023-10-30 23:04:07 24 4
gpt4 key购买 nike

我在应用程序中遇到了内存问题,我已经能够将其分解为 NSCalendar。

像这样一个简单的 View Controller :

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

while Calendar.current.component(.year, from: Date()) > 0
{
// why does the memory keep increasing?
}
}
}

似乎会导致内存泄漏。

这个例子显然会阻塞 UI 线程,但它不应该导致内存不断增加,或者至少在循环完成后被释放。好吧,至少根据我的理解,它不应该。我在这里误解了一些基本的东西吗?或者这是一个错误?

我该如何解决这个问题?

更新

引自评论:

FYI - your issue has nothing to do with NSCalendar. Your issue is your while loop never allowing memory to be cleaned up

All of those Date instances are taking up memory too

好吧,但是如果我运行一个只有日期比较的循环,我就不会遇到同样的问题。这是因为优化器介入了吗?

while Date() > Date(timeIntervalSince1970: 200)
{
// no increase of memory here
}

最佳答案

正如其他人所指出的,问题在于 Calendar.current.component(_:from:) 在幕后引入了一个自动释放对象,该对象直到自动释放池被排空。

在引用计数 Objective-C 代码的早期,返回一个新分配的对象的常见方法是返回一个“autorelease”对象,该对象将在调用者完成使用后自动释放。这是一个只有当你回到运行循环时才会被释放的对象,这会耗尽 autorelease pool。 .您可以通过添加自己的手动自动释放池来控制重复创建自动释放对象的大循环的高水位线。

Swift 本身不会创建自动释放对象,因此这个问题有点像 Objective-C 的时代错误,我们在自己的 Swift 代码中通常不会遇到这种情况。但是,每当编写循环代码并调用可能在幕后使用自动释放对象的 Cocoa API 时,我们都必须对此保持敏感,例如在本例中。

在我深入研究解决方案之前,我将调整您的示例以确保最终退出。例如,让我们编写一个例程,该例程一直旋转直到与当前时间关联的 minute 发生变化(例如,当前分钟结束和下一分钟开始时)。我们假设 previousValue 包含当前的 minute 值。

诀窍是我们需要把autoreleasepool 循环中。在下面的示例中,我们利用了 autoreleasepool 是通用的这一事实,它返回其闭包内返回的任何内容:

while autoreleasepool(invoking: { Calendar.current.component(.minute, from: Date()) }) == previousValue {
// do something
}

请注意,如果您发现该模式难以阅读(需要一段时间才能习惯将闭包作为方法的参数),您可以使用 repeat-until循环,以完成大致相同的事情:

var minute: Int!
repeat {
minute = autoreleasepool {
Calendar.current.component(.minute, from: Date())
}

// do something
} while minute == previousValue

顺便说一句,这种让循环像这样快速旋转的过程效率非常低。当然,正如您提到的,您永远不会在主线程上执行此操作(因为我们永远不想阻塞主线程)。但是您通常不会在任何 线程上执行此操作,因为旋转的计算量非常大。有时你必须这样做(例如,无论如何在后台线程上做一些复杂的计算并且你希望它在某个特定时间停止),但十有八九是设计中更深层次问题的代码味道。通常明智地使用定时器等可以实现预期的效果,而无需计算开销。

很难就您的情况向您提供最佳解决方案建议,因为我们不知道您要解决的更广泛问题是什么。但请注意,在线程上自旋通常是不可取的。


你问:

Well but if I run a loop with just a date comparison im not running into the same issue. Is this because the optimiser steps in?

不,这仅仅是因为 Date() 根本没有像 Calendar.current.component(_:from:) 那样引入任何自动释放对象。 (顺便说一句,Apple 擅长在整个代码库中慢慢删除自动释放对象,因此您可能会在未来的某个时候发现,即使这可能不需要手动自动释放池。)

关于ios - Swift Calendar.current 内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52047297/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com