- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在应用程序中遇到了内存问题,我已经能够将其分解为 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/
也许是一个愚蠢的问题,但我有一个在 Java 文档中没有找到的问题。 Calendar.get(Calendar.DAY_OF_WEEK) 的值是否会根据 Calendar.getFirstDayOf
假设以下代码在 2009 年 8 月 22 日(星期六)执行 Calendar c = Calendar.getInstance(); c.set(Calendar.DAY_OF_WEEK
我正在使用以下代码检查所选月份是否为一月: if (calendar.get(Calendar.MONTH) == Calendar.JANUARY) { ... } 这给了我一个 lint
我有两个 Calendar 变量,分别命名为 calendar1 和 calendar2 其中存储了一些日历值。 我想比较这些变量的 MINUTE 值。 我找到了两种方法,但我想知道有什么区别以及哪一
根据文档 ( here ),Google 提供了一些相同的范围: https://www.googleapis.com/auth/calendar读/写访问到日历 https://www.google
我想问一下,是否可以在不调用 Google 日历 API(需要互联网连接)或启动 native 日历 Activity (不需要)的情况下添加日历事件?只需将日历事件添加到设备 native 日历中(
我们可以从谷歌日历设置中获取工作时间数据吗?我已经了解了日历的 API : https://developers.google.com/calendar/v3/reference/settings/g
我正在尝试使用 Exchange Web 服务访问日历数据,但我似乎无法弄清楚如何访问其他用户共享的日历(当它不是他们的默认日历时)。假设我公司的另一个用户创建了一个共享日历并与我共享,我什至找不到日
我对 Java/Android 中的日期比较有点困惑 DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm");
我正在使用Google的Calendar API,但遇到了一个问题。当我设置要插入的事件的dateTime时,需要设置小时偏移量,但是由于o DST的原因,它需要一个小时。我可以为日历设置一个属性,以
在Google日历的常规网络用户界面中,当我添加事件时,可以选择将其设置为“提醒”,而不是“事件”。 我正在尝试使用Python API进行复制,但是似乎找不到有关如何执行该操作的信息。我找到的所有文
我们可以使用这个link通过参数向Google日历添加新事件 https://www.google.com/calendar/render? action=TEMPLATE& text=EventNa
除了在纪元显式设置它们之外,是否有任何现有方法可以使用日历 API 来获取填充纪元时间的日历?我所能做的就是获取当前时间。 最佳答案 没有预定义的构造函数或工厂方法来执行此操作,但它相当简单: Cal
我试图在我的应用程序上次更新时显示在 TextView 中(例如,“上次更新时间为 12:13”)。我正在尝试使用 Calendar 实例,我认为我理解正确,但我似乎遇到了麻烦. 我知道要获取一个实例
这个问题在这里已经有了答案: Calendar.before(Object when), why Object? (3 个答案) 关闭 8 年前。 我遇到了问题,因为我试图将日期传递给 Calend
在IOS5上使用获取所有日历时 EKEventStore *eventStore = [[EKEventStore alloc] init]; NSArray * calendars = [event
当我运行以下代码时: int year = 2017; int month = 7; int dayOfMonth = 10; Calendar dateOfBirth = new Gregorian
要么我不理解方法 getActualMaximum(int) 或字段 WEEK_OF_YEAR,要么涉及 Sun 错误(或所有三个)...有人可以向我解释为什么(至少在德语语言环境中...) 以下代码
我正在检查我几年前写的代码。然后我意识到 Android Studio 在 Calendar.AM 处给出了注释,它说它必须是 Calendar.SUNDAY、Calendar.MONDAY 之一等等
我需要将给定日期复制 100 次(我无法通过引用传递)。我想知道以下两个中哪个是更好的选择 newTime=Calendar.getInstance().setTime(originalDate);
我是一名优秀的程序员,十分优秀!