您的位置:首页 > 移动开发 > Objective-C

ObjectMapper与CoreData结合使用在类初始化时出现访问违例的分析和解决

2018-10-20 16:49 615 查看
版权声明:大熊猫猪·侯佩原创或翻译作品.谢绝转载! hopy https://blog.csdn.net/mydo/article/details/83214738

ObjectMapper是一个便捷的Swift类和JSON互转的库,它为iOS实体模型多提供了一种实现方法.

它可以和CoreData配合完成一些有趣的功能.

但在使用过程中在感受到便捷的同时也发现了一些问题,记录下来供自己和大家参考.

CoreData托管某类实例变量如下:

@NSManaged public var date: Date
@NSManaged public var remark: String?
@NSManaged public var resultString: String
@NSManaged public var habit: Habit?

在其扩展中实现Mappable协议:

public func mapping(map: Map) {
date <- (map["traceDate"],DateTransform())
remark <- map["remark"]
resultString <- map["resultString"]
habit <- (map["habit"],Transforms.transformForHabit)
}

需要说明的是,除了一些常见的类型(比如Int,String等),需要在映射时设置合适的转换器.如上所示,对于Date和Habit?类型,分别使用了内置的和我自定义的转换器.

如果不设置,ObjectMapper转换也不会出错,它只是不转换该实例变量而已…

对于自定义转换器的编写也很简单,但超出了本博的主旨,所以有机会单开一个系列再表(先挖坑,填不填另说…)

就这个例子,在托管类初始化时App崩溃了,提示访问违例:

let longHabit = model.allHabits.filter {$0.title.hasPrefix("very")}.first!
let date = "2018-9-3".toDate()!.dayBegin
let traces = longHabit.tracesByDays[date]!
let trace = traces[0]
let json = trace.toJSONString()!
let new_trace = HabitTrace(JSONString: json)	//Crash Here!

我分析原因可能和托管类的托管属性有关!

对于在托管类中被@NSManaged修饰的非可nil实例变量来说,必须在访问前就设置好其值,否则会崩溃!但是对于一些简单类型来说(比如String等),如果你不初始化则自动赋予一个合理的"空值",注意该"空值"不是nil,对于字符串来说它是:""

你可以先赋值,再取值,但万万不可不赋值就取值:

这就是为什么访问date会崩,而访问同样非可nil变量resultString却没问题的原因.

当然如果任何类型是可nil的话,就不存在这个问题了…

所以在该托管类的map初始化器中,我们要给date变量赋予一个值,一种做法是:

public required init?(map: Map) {
//初始化description和ctx值
super.init(entity: description, insertInto: ctx)

date = Date()
}

不过更为恰当的做法是赋予一个"空值":

date = Date(timeIntervalSince1970: 0)

不管你赋予何值,正常情况下他都会被随后的map映射器自动帮你重新设置!不过它的参考来源自然是JSON了. 😉

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐