使用 Realm 保存数据数组或自定义 类
Save arrays of data or custom classes with Realm
我有一个自定义 class 保存着很多信息。这是一个位置跟踪应用程序,所以我稍后需要位置(基本上只有 x、y、z,但为了方便我使用 CLLocations)。
现在我有一个自定义 class 保存有关每个跟踪的所有信息,如 record/save 文件)。我使用 Realm 来保存它,Realm 可以很好地处理我的双打和字符串,但我在处理数据数组时遇到了麻烦。
我能找到的最方便的解决方案是将数据转换为 NSData。在 Google 的帮助下,我找到了两种编码和解码的方法。但是我没有这方面的经验,所以我不确定它是否有效。而且我认为这行不通。
我可以很好地加载双打和字符串,但我的 NSData 似乎是空的。我试图将我的 class 编码为 NSData 并将其保存在 Realm 中,但这似乎不起作用,因此我认为 encode/decode 函数无法正常工作。
TL;DR 我有我的自定义 class(数据记录),我想用 Realm 保存。我该如何解决这个问题?
我的class:
class DataRecord {
var startLocation : CLLocation = CLLocation.init()
var endLocation : CLLocation = CLLocation.init()
var duration : Double = 0.0
var distance: Double = 0.0
var avgSpeed : Double = 0.0
var topSpeed : Double = 0.0
var locations : [CLLocation] = []
var altitudes : [Double] = []
var angles : [Double] = []
var speeds : [Double] = []
}
我的 NSData encode/decoder
func encode<T>(value: T) -> NSData {
var val = value
return withUnsafePointer(&val) { p in
NSData(bytes: p, length: sizeofValue(value))
}
}
func decode<T>(data: NSData) -> T {
let pointer = UnsafeMutablePointer<T>.alloc(sizeof(T.Type))
data.getBytes(pointer, length: sizeof(T))
return pointer.move()
}
Realm class 和我的记录几乎一样,因此只对记录进行编码并将其保存到 Realm 会更容易。但这里是:
class Record: Object {
dynamic var name = ""
dynamic var locations = NSData()
dynamic var altitudes = NSData()
dynamic var angles = NSData()
dynamic var speeds = NSData()
dynamic var distance = 0.0
dynamic var duration = 0.0
dynamic var topSpeed = 0.0
dynamic var avgSpeed = 0.0
dynamic var topAngle = 0.0
dynamic var avgAngle = 0.0
}
Realm 仅支持基本数据类型,因此您需要 'translate' 来自 CLLocation
的数据到 Realm 可以存储的内容是正确的。
在这种情况下,与其尝试将 CLLocation
序列化为 NSData
,不如创建另一个 Realm Object
子类来保存与CLLocation
,并且可以即时创建该类型的对象。
此外,虽然它有些限制,但 Realm 只能在其 List
属性中存储其他 Realm Object
s。所以在这种情况下,有必要将其他值(例如海拔等)也包装在它们自己的领域 Object
子类中。
class Location: Object {
dynamic var latitude = 0.0
dynamic var longitude = 0.0
var clLocation: CLLocation {
return CLLocation(latitude: self.latitude, longitude: self.longitude)
}
init(clLocation: CLLocation) {
self.latitude = clLocation.latitude
self.longitude = clLocation.longitude
}
}
class Altitude: Object {
dynamic var altitudeValue = 0.0
}
class Angle: Object {
dynamic var angleValue = 0.0
}
class Speed: Object {
dynamic var speedValue = 0.0
}
class Record: Object {
dynamic var name = ""
dynamic var startLocation: Location?
dynamic var endLocation: Location?
dynamic var distance = 0.0
dynamic var duration = 0.0
dynamic var topSpeed = 0.0
dynamic var avgSpeed = 0.0
dynamic var topAngle = 0.0
dynamic var avgAngle = 0.0
let locations = List<Location>()
let altitudes = List<Altitude>()
let angles = List<Angle>()
let speed = List<Speed>()
}
如果您的模型 class 确认 NSCoding 协议,那么您可以按照以下方式将其放入 Realm。
示例:
路线是我的模型结构。
struct Route {
fileprivate (set) var locations: [CLLocation]
init() {
locations = []
}
init(withLocations locations: [CLLocation]) {
self.locations = locations
}
}
RouteRealm 正在包装 Route 使得将对象保存到 Realm 成为可能
class RouteRealm: Object {
dynamic var locations: Data? = nil
convenience init(route: Route) {
self.init()
self.locations = NSKeyedArchiver.archivedData(withRootObject: route.locations)
}
func route() -> Route {
if let locations = locations,
let clLocations = NSKeyedUnarchiver.unarchiveObject(with: locations) as? [CLLocation] {
return Route(withLocations: clLocations)
}
return Route()
}
}
存储空间:
struct RealmStore: DataStore {
let realm = try! Realm()
func store(route: Route) {
let routeRealm = RouteRealm(route: route)
try! realm.write {
realm.add(routeRealm)
}
}
func routes() -> [Route] {
let routesRealm = realm.objects(RouteRealm.self)
let routes = routesRealm.map() { [=12=].route() }
return Array(routes)
}
}
protocol DataStore {
func store(route: Route)
func routes() -> [Route]
}
我有一个自定义 class 保存着很多信息。这是一个位置跟踪应用程序,所以我稍后需要位置(基本上只有 x、y、z,但为了方便我使用 CLLocations)。 现在我有一个自定义 class 保存有关每个跟踪的所有信息,如 record/save 文件)。我使用 Realm 来保存它,Realm 可以很好地处理我的双打和字符串,但我在处理数据数组时遇到了麻烦。
我能找到的最方便的解决方案是将数据转换为 NSData。在 Google 的帮助下,我找到了两种编码和解码的方法。但是我没有这方面的经验,所以我不确定它是否有效。而且我认为这行不通。
我可以很好地加载双打和字符串,但我的 NSData 似乎是空的。我试图将我的 class 编码为 NSData 并将其保存在 Realm 中,但这似乎不起作用,因此我认为 encode/decode 函数无法正常工作。
TL;DR 我有我的自定义 class(数据记录),我想用 Realm 保存。我该如何解决这个问题?
我的class:
class DataRecord {
var startLocation : CLLocation = CLLocation.init()
var endLocation : CLLocation = CLLocation.init()
var duration : Double = 0.0
var distance: Double = 0.0
var avgSpeed : Double = 0.0
var topSpeed : Double = 0.0
var locations : [CLLocation] = []
var altitudes : [Double] = []
var angles : [Double] = []
var speeds : [Double] = []
}
我的 NSData encode/decoder
func encode<T>(value: T) -> NSData {
var val = value
return withUnsafePointer(&val) { p in
NSData(bytes: p, length: sizeofValue(value))
}
}
func decode<T>(data: NSData) -> T {
let pointer = UnsafeMutablePointer<T>.alloc(sizeof(T.Type))
data.getBytes(pointer, length: sizeof(T))
return pointer.move()
}
Realm class 和我的记录几乎一样,因此只对记录进行编码并将其保存到 Realm 会更容易。但这里是:
class Record: Object {
dynamic var name = ""
dynamic var locations = NSData()
dynamic var altitudes = NSData()
dynamic var angles = NSData()
dynamic var speeds = NSData()
dynamic var distance = 0.0
dynamic var duration = 0.0
dynamic var topSpeed = 0.0
dynamic var avgSpeed = 0.0
dynamic var topAngle = 0.0
dynamic var avgAngle = 0.0
}
Realm 仅支持基本数据类型,因此您需要 'translate' 来自 CLLocation
的数据到 Realm 可以存储的内容是正确的。
在这种情况下,与其尝试将 CLLocation
序列化为 NSData
,不如创建另一个 Realm Object
子类来保存与CLLocation
,并且可以即时创建该类型的对象。
此外,虽然它有些限制,但 Realm 只能在其 List
属性中存储其他 Realm Object
s。所以在这种情况下,有必要将其他值(例如海拔等)也包装在它们自己的领域 Object
子类中。
class Location: Object {
dynamic var latitude = 0.0
dynamic var longitude = 0.0
var clLocation: CLLocation {
return CLLocation(latitude: self.latitude, longitude: self.longitude)
}
init(clLocation: CLLocation) {
self.latitude = clLocation.latitude
self.longitude = clLocation.longitude
}
}
class Altitude: Object {
dynamic var altitudeValue = 0.0
}
class Angle: Object {
dynamic var angleValue = 0.0
}
class Speed: Object {
dynamic var speedValue = 0.0
}
class Record: Object {
dynamic var name = ""
dynamic var startLocation: Location?
dynamic var endLocation: Location?
dynamic var distance = 0.0
dynamic var duration = 0.0
dynamic var topSpeed = 0.0
dynamic var avgSpeed = 0.0
dynamic var topAngle = 0.0
dynamic var avgAngle = 0.0
let locations = List<Location>()
let altitudes = List<Altitude>()
let angles = List<Angle>()
let speed = List<Speed>()
}
如果您的模型 class 确认 NSCoding 协议,那么您可以按照以下方式将其放入 Realm。
示例: 路线是我的模型结构。
struct Route {
fileprivate (set) var locations: [CLLocation]
init() {
locations = []
}
init(withLocations locations: [CLLocation]) {
self.locations = locations
}
}
RouteRealm 正在包装 Route 使得将对象保存到 Realm 成为可能
class RouteRealm: Object {
dynamic var locations: Data? = nil
convenience init(route: Route) {
self.init()
self.locations = NSKeyedArchiver.archivedData(withRootObject: route.locations)
}
func route() -> Route {
if let locations = locations,
let clLocations = NSKeyedUnarchiver.unarchiveObject(with: locations) as? [CLLocation] {
return Route(withLocations: clLocations)
}
return Route()
}
}
存储空间:
struct RealmStore: DataStore {
let realm = try! Realm()
func store(route: Route) {
let routeRealm = RouteRealm(route: route)
try! realm.write {
realm.add(routeRealm)
}
}
func routes() -> [Route] {
let routesRealm = realm.objects(RouteRealm.self)
let routes = routesRealm.map() { [=12=].route() }
return Array(routes)
}
}
protocol DataStore {
func store(route: Route)
func routes() -> [Route]
}