首页 > 解决方案 > 带有 iOS 10.3 的 iPhone 5 和 iPad 4th gen 上非常烦人的 NSPredicate 崩溃

问题描述

正如这个问题的标题所说,下面我的代码在NSPredicate初始化时崩溃了。到目前为止,我发现只有在 iOS 10.3 的 iPhone 5 和 iPad 4th gen 上才会发生崩溃。在具有相同 iOS 10.3 的其他设备上一切正常。

func getPredicate(for serviceId: Int64, startingFrom step: Int) -> NSPredicate {
    let predicate = NSPredicate(format: "serverID == %i AND step == %i AND type == %@", 
                                serviceId, step, "button")
    return predicate
}

这篇文完美地描述了我的问题,我在 32 位 CPU 设备上也遇到了同样的崩溃问题。虽然帖子中给出的解决方案帮助我停止了崩溃,但是当我在 fetch 请求中使用它时CoreData总是返回结果。nil

有什么办法可以解决这个问题吗?

开发工具:

标签: iosswiftnspredicate

解决方案


%i格式用于格式化 Cint类型的值,在所有当前 iOS 平台上都是 32 位整数。改为传递 64 位整数(在您的情况下serviceId:)是未定义的行为,可能会导致崩溃。

64 位整数的正确格式是%lli(for long long int),而Int(可以是 32 位或 64 位)的正确格式是%li(for long int)。

所以这适用于 32 位和 64 位设备:

let predicate = NSPredicate(format: "serverID == %lli AND step == %li AND type == %@",
                            serviceId, step, "button")

一种“更简单”的方法是将所有数字转换为NSNumber,因为您不必记住各种整数类型的正确格式。NSNumbers 是“对象”(Objective-C 类的实例),可以简单地使用以下格式进行格式化%@

let predicate = NSPredicate(format: "serverID == %@ AND step == %@ AND type == %@",
                            serviceId as NSNumber, step as NSNumber, "button")

将参数作为 an 传递argumentArray 可能是偶然的,但如果格式错误,它仍然是未定义的行为。


推荐阅读