【发布时间】:2015-03-18 23:06:58
【问题描述】:
我在开始的 Swift 项目中遇到问题。我使用 Alamofire 进行网络连接,使用 MagicalRecord 作为 Core Data 的包装器。我不知道这是否重要,但我还是要提一下。
设置
应用程序正在从 JSON API 检索其数据。使用Alamofire's Generic Response Object Serialization,我创建了Alamofire.Request 的扩展,如链接页面所示,并实现了以下协议:
@objc public protocol ResponseObjectSerializable {
init?(response: NSHTTPURLResponse, representation: AnyObject)
}
我创建的类是这样的:
final class Foo: ResponseObjectSerializable {
let bar: String
let baz: String
required init?(response: NSHTTPURLResponse, representation: AnyObject) {
self.bar = representation.valueForKeyPath("bar") as String
self.baz = representation.valueForKeyPath("baz") as String
}
}
要检索 JSON 数据并将其序列化为 Foo,我只需执行以下操作:
Alamofire.request(.GET, "http://foo.com/api").responseObject { (_, _, foo: Foo?, _) in
println(foo.bar)
}
到目前为止,一切都很好。
问题:添加核心数据
当我想添加 Core Data 功能时,问题就开始了。我想使用上述方法从 API 中检索数据,对其进行序列化,并在某些时候使用 Core Data 将其保存。
所以,我决定将上面的Foo 类调整为:
@objc(Foo)
final class Foo: NSManagedObject, ResponseObjectSerializable {
@NSManaged var bar: String
@NSManaged var baz: String
required init?(response: NSHTTPURLResponse, representation: AnyObject) {
self.bar = representation.valueForKeyPath("bar") as String
self.baz = representation.valueForKeyPath("baz") as String
}
}
这不起作用,因为 NSManagedObject 子类需要指定的初始化程序,所以我将我的类更改为:
@objc(Foo)
final class Foo: NSManagedObject, ResponseObjectSerializable {
@NSManaged var bar: String
@NSManaged var baz: String
convenience required init?(response: NSHTTPURLResponse, representation: AnyObject) {
let context = NSManagedObjectContext.defaultContext()
let entity = NSEntityDescription.entityForName("Foo", inManagedObjectContext: context)
self.init(entity: entity!, insertIntoManagedObjectContext: context)
self.bar = representation.valueForKeyPath("bar") as String
self.baz = representation.valueForKeyPath("baz") as String
}
}
错误
该项目确实编译了,这看起来很有希望,但会引发以下错误:
架构 x86_64 的未定义符号:
“__TFC7Project3Foo3barSS”,引用自:TFC7Project3FoocfMS0_FT8responseCSo17NSHTTPURLResponse14representationPSs9AnyObject__GSqS0 在 Foo.o
ld:未找到体系结构 x86_64 的符号
clang:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)
我不知道为什么会导致该错误,我真的很想摆脱它。那么,有谁知道如何解决这个问题?任何帮助表示赞赏。
我为什么要使用这种方法?
我的 iOS 应用中有搜索功能(在模式中)。搜索结果被列为 Foo 实例,但我没有在本地保存它们中的任何一个(还)。这种方法只是在 UITableView 中轻松列出检索到的 JSON 数据的一种便捷方式。
一旦(从该列表中)选择了搜索结果,我想使用 Core Data 将该特定项目添加到本地数据库。只有那些已保存的项目才会在应用程序的主视图中列出。在我看来,使用相同的类似乎很方便。
我尝试过的(除了上面的)
在创建这个问题之前,我尝试在谷歌上搜索一些解决方案(但可以找到任何可行的答案)并使用此站点上的搜索功能。我发现了几个(有点)相关的问题:
根据this answer,我必须使用Xcode 6.3 beta,我已经尝试过(6D543q),但这也不起作用。我目前正在使用Xcode 6.2 (6C131e) btw。
另一个似乎相关的问题有以下answer。所以,我在变量声明中添加了dynamic:@NSManaged dynamic var bar: String,但这也不起作用。
注意事项
我还想指出,我是 iOS(和 Swift)的新手,所以我可能没有使用正确的(或者我应该说是推荐的)方法。如果是这种情况,请告诉我,以便我采取其他可能不会导致此错误的方法。
【问题讨论】:
-
我正在尝试做同样的事情 - 我正在重构一些初始的 swift/核心数据工作 - 并试图将序列化代码移动到托管对象模型中(如 alamofire 文档中所述) 并在本 Wenderlich 教程中:raywenderlich.com/87595/intermediate-alamofire-tutorial
-
我想知道是否有更好的封装 - 保持核心数据模型干净 - 并使用由您的对象模型类组成的另一个对象,也符合 ResponseObjectSerializable...
-
@DanielD 尽管我给出的答案对我有用,但它仍然是一个 hack 或者实际上是一个 临时 解决方法。我不太喜欢这种方法,但是一旦它在编译器中得到修复,我就可以删除
*.c文件并完成它。它在 Objective-C 中工作,所以它可能会被修复。无论如何,我一直在考虑另一种方法,使用两个对象。一个符合 ResponseObjectSerializable 协议,另一个是漂亮而干净的核心数据模型(就像你说的那样)。我只需要在保存之前将第一个的属性应用于后者。
标签: ios swift core-data nsmanagedobject alamofire