Swift 项目使用 CoreData 可能会碰到的 32 位系统问题

最近在项目中偶然发现了一个问题,那就是 Swift 的 CoreData 在 32 位系统下与 64 位系统下表现不一致的问题。

简单的说:如果你的 CoreData 模型有一个声明为 Boolean 的 Attribute,并且在代码中使用 NSNumber 来包装(而不是 Bool)的话,很可能会遇到这个问题。

这个问题简述之则是这样:

假如有一个 Post 的 CoreData 类型,它有一个 isPublished 的属性,CoreData 使用 NSNumber 来包装这个属性。我对其进行赋值:

post.isPublished = true

没错,虽然 isPublished 在代码中是 NSNumber 类型,但是得益于 Swift 的「Literal Convertibles」机制,我们可以直接给 NSNumber 赋值 true,然后它就会以 true 存储。

问题就在这里出现了。如果是在 32 位的系统下,我用

if post.isPublished == true {

}

进行条件判断,那么很遗憾不会走进这个条件分支里,在 64 位系统下是正常的。

如果改成:

if post.isPublished == 1 {

那么无论在 32 位和 64 位系统下都是正常的。

发现这个问题的,开始想解决方法,假设这真的是 Swift 在 32 位系统下的 Bug,难道我要把这些比较都改成 1 或 0?

后来我找到一个方法,那就是创建 CoreData 的 NSManagedobject 的 class 的时候,勾上那个 Option:Use scalar properties for primitive data types,这样 isPublished 就不是用 NSNumber 这种包装型的,而是直接用 Bool 类型了。经测试,无论在 32 位系统下还是 64 位系统下,条件判断都工作正常了。算是优雅地绕开了这个可能是 Swift 的 Bug。

后来我又尝试了下不用 CoreData,直接用 NSNumber = false 的形式来进行判断,发现没有这个问题。看来这个问题可能只存在 CoreData 上。

既然写起了 Swift + CoreData 这个组合,免不了需要吐槽一个 Apple 做的还不好的地方:

以往 Objective-C 项目时,CoreData 对象的一个属性是不是空值,我们直接判断是不是 nil 就可以了,但是在 Swift 项目下,一切变得麻烦了,Xcode 认给我们产生的 CoreData 对象的属性,全都不是optional 的,也就是说,如果一个属性可能是空值,我们还要手动给这个加上一个「?」,它才会如我们所愿可以用 Optional 的方式。这点实在是很不方便。

具体可以看一个帖子:Swift + CoreData: Cannot Automatically Set Optional Attribute On Generated NSManagedObject Subclass

OK,希望接下去不要碰到太多类似的坑。

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...