iOS NSCalendar 崩溃 - 参考问题?
Posted
技术标签:
【中文标题】iOS NSCalendar 崩溃 - 参考问题?【英文标题】:iOS NSCalendar Crash - References issue? 【发布时间】:2014-07-08 05:13:47 【问题描述】:我看到了一些崩溃,所有的表现都略有不同,但它们都指向同一行代码,我有一种预感,但它有点超出了我的舒适区,所以我想一些帮助。
崩溃与 NSCalendar 的组件有关:fromDate。
在有问题的类中有一个 NSCalendar 的实例变量,在我的 init 方法中我调用了
calendar = [NSCalendar autoupdatingCurrentCalendar];
稍后我打电话:
NSDateComponents *components = [calendar components:myComponents fromDate:myDate];
上面一行是发生崩溃的地方,当查看崩溃日志时,我看到这一行的错误组合:
EXC_BAD_ACCESS KERN_INVALID_ADDRESS [__NSCFNumber components:fromDate:]:发送到实例的选择器无法识别 NSInvalidArgumentException [__NSDate components:fromDate:]:发送到实例的选择器无法识别 SIGABRT 中止我已经检查过了,除了在 init 方法中的初始创建之外,我没有在任何地方更改日历变量。正如我所说,我没有在代码中的任何地方修改日历变量,也无法复制任何其他问题,但我通过执行以下操作复制了第二次崩溃:
NSCalendar *calendar = @5;
NSDateComponents *components = [calendar components:myComponents fromDate:myDate];
这可能是某种内存引用问题吗?我已经看到几年前在 ARC 之前的 SO 帖子上报告了类似的问题(遗憾的是,我从来没有在没有 ARC 的情况下做过任何事情),人们没有正确地保留他们的变量。这可能是某种问题,其中实例变量没有正确保留,使内存处于不良状态,导致这些奇怪且看似不同的问题,但都在同一个地方?非常感谢任何和所有信息。
编辑:我要补充一点,这是 crashlytics 报告的罕见/间歇性崩溃,我无法多次复制到本地调试,这让我相信它要么是内存管理问题,要么可能是内存管理问题线程问题。
第二次编辑:我回顾了一些我在 Xcode 中发现这个问题时的截图/日志内容,我想我错过了一些东西。
如果我在该行设置断点,并打印日历对象:
po calendar
0x14d50a20
如果我通常在全新的 [NSCalendar autoupdatingCurrentCalendar] 上执行 po,我会得到:
自动更新日历 [<_nscopyonwritecalendarwrapper:>]
这是否意味着在它只是一个地址的情况下,对象就像我最初预期的那样丢失了?
【问题讨论】:
我不知道你在做什么,但那些崩溃是因为你试图在 NSNumber 和 NSDate 上调用方法“组件:...”。我不明白您为什么将日历设置为 @5,这意味着您将其设置为 NSNumber。 如果你在麻烦的行之前记录日历,它会给你什么。 您在初始化components
的方法中使用components
。所以右边的components
是未初始化的。
当然,您可以通过在每次使用之前立即提取calendar
来回避这个问题。
这是一个很难破解的问题。我今天正在研究类似(但不相同)的东西,我认为这是由于一些 UI 访问不是从主线程完成的。但是,当然,您永远无法确定问题是否消失了。
【参考方案1】:
虽然 Ritu 注意到了这一点,但还有更多值得一提的地方。我仍然不确定这是内存问题、线程问题还是两者的组合(很有可能),但每次我需要解决问题时,我都会删除实例变量并直接访问 autoupdatingCurrentCalendar。这是因为调用 [NSCalendar autoupdatingCurrentCalendar] 每次都会返回一个唯一的实例,这是我最初不会想到的。
因此,摆脱 NSCalendar 实例变量并将对该变量的每次调用替换为获取 autoupdatingCurrentCalendar 的调用将解决从多个线程访问相同引用的任何问题,以及对象是否会损坏、丢失、发布等,出于任何原因。
【讨论】:
如果你支持 ios 6,那些NSCalendar
factory 调用可能会非常昂贵。我使用的是currentCalendar
,而不是自动更新的,发现在 6 岁以下,在线程字典中粘贴一个副本会缩短显示时间的 10%,以显示与它们相关的日期计算的小表格。 7以下没有区别;苹果似乎已经解决了这个问题。
还好我只支持iOS7,但知道这绝对是好事!【参考方案2】:
你应该使用:
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]];
【讨论】:
以上是关于iOS NSCalendar 崩溃 - 参考问题?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 NSCalendar 的情况下创建 NSDates(一天的开始和结束)?