【问题标题】:Swift EXC_BREAKPOINT crash on NSDateComponents access with iOS 10.x but not 11.xSwift EXC_BREAKPOINT 在使用 iOS 10.x 而不是 11.x 访问 NSDateComponents 时崩溃
【发布时间】:2018-07-15 17:09:47
【问题描述】:

我收到了在 iOS 10.3 上运行的应用实例的 EXC_BREAKPOINT 崩溃报告,但在任何较新的 iOS 上都没有。

问题似乎在于访问-[NSDateComponents minute]

这是 Crashlytics 的摘要:

EXC_BREAKPOINT 0x00000000e7ffdefe

# OS Version: 10.3.3 (14G60)
# Device: iPhone 5c
# RAM Free: 5.8%
# Disk Free: 17%

#0. Crashed: com.apple.main-thread
0  MyApp                     0x1d91940 specialized static TimeUtility.annualCycleIndex(comps:comps0:) (TimeUtility.swift:53)
1  CoreFoundation                 0x1d05ecd5 -[NSDateComponents minute] + 8
2  MyApp                     0x1d91ad0 specialized static TimeUtility.exampleCall(date:date0:) (TimeUtility.swift:71)
3  MyApp                     0x1d82bac 

该应用面向 iOS 9。 实际代码如下所示:

public class TimeUtility {

    public class func annualCycleIndex(comps: DateComponents, comps0: DateComponents) throws -> Int {

        // Abstract durations in seconds
        let minuteUnit = 60
        let hourUnit = 60 * minuteUnit
        let dayUnit = 24 * hourUnit
        let monthUnit = 30 * dayUnit
        let yearUnit = 12 * monthUnit

        // Full years count between date and date0

        guard let y0 = comps0.year, let m0 = comps0.month, let d0 = comps0.day, let hh0 = comps0.hour, let mm0 = comps0.minute, let ss0 = comps0.second else {
            throw MyAppError.processingError(function: #function, descr: "Failed to extract all required date components")
        }

        guard let y = comps.year, let m = comps.month, let d = comps.day, let hh = comps.hour, let mm = comps.minute, let ss = comps.second else {
            throw MyAppError.processingError(function: #function, descr: "Failed to extract all required date components")
        }

        // <--- XXX: Crash seems to happen somewhere here

        let t0 = y0 * yearUnit + m0 * monthUnit + d0 * dayUnit + hh0 * dayUnit + mm0 * minuteUnit + ss0
        let t = y * yearUnit + m * monthUnit + d * dayUnit + hh * dayUnit + mm * minuteUnit + ss

        return periodicCycleIndex(t: t, t0: t0, measure: yearUnit)
    }

    public class func exampleCall(date: Date, date0: Date) throws {

        let calendar = Calendar(identifier: .gregorian)
        let timeZone = TimeZone(secondsFromGMT: 0)!

        let comps0 = calendar.dateComponents(in: timeZone, from: date0)
        let comps = calendar.dateComponents(in: timeZone, from: date)

        let _ = try annualCycleIndex(comps: comps, comps0: comps0)

        // some other code...
    }

    public class func periodicCycleIndex(t: Int, t0: Int, measure: Int) -> Int {
        // Some other code...
        return 0
    }
}

public enum MyAppError : Error {
    case processingError(function: String, descr: String)
    case unknownError(error: Error)

    public var localizedDescription: String {
        switch self {
        case .processingError(let f, let s):
            return "Failed to process request in function: \(f), description: \(s)"
        case .unknownError(let err):
            return "Unknown error: \(err)"
        }
    }
}

这可能是因为 Objective-C 在 Swift 可以访问它之前以某种方式释放了 NSDateComponent 吗?不知道有没有人有这样的东西...

我也尝试过访问-[NSDateComponents seconds],但还是同样的崩溃,只是指秒组件。

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    关键是注意到它是 iPhone 5c,后来我看到了其他一些崩溃 - 全部来自 32 位设备。发生的情况是,在某些情况下,Swift 代码会尝试访问 NSDateComponents 的成员,就好像它们是 64 位整数一样,而在这些设备上它们实际上是 32 位 Objective-C 整数。

    我怀疑每个新应用发布的现代 Swift 代码的编译方式都可能与旧版 32 位设备产生细微的不兼容性。需要注意的事项。

    在我的情况下,不使用NSDateComponents 而是使用TimeInterval 而是Double,并且在任何有助于修复崩溃的系统上都将保持双倍。

    【讨论】:

    • 不就是整数溢出吗?请记住,Int 在 32 位设备中是 32 位长的。当 y &gt;= 70 在 32 位计算中时,表达式 let t = y * yearUnit... 溢出。无论如何,使用Double 似乎是正确的解决方案,或者Int64 会起作用。
    • 是的,我同意。崩溃报告让我与-[NSDateComponents minute] + 8 混淆了,这让我认为 Obj-C 到 Swift 的桥接失败,而 let t = y * yearUnit... 应该是原因。关键学习:在计算中远离使用 NSDateComponents...或者转换为正确的IntXX 类型
    猜你喜欢
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多