有谁知道如何使用Realm存储字符串数组?我正在尝试将以下响应正确映射到Realm中:
"zoneInfo": {
"tariffInfoLines": [
"In this city you pay per minute."
]
}
我们有一个包含tariffInfoLines数组的zoneInfo对象。此tariffInfoLines数组包含字符串。在Realm中,有两种不同的变量类型用于存储数据。第一个是RLMObject,它允许你的标准NSString,int,long等。
第二种类型是RLMArray,用于数组(不支持NSArray)。您必须为数组提供一个类型,该类型必须是RLMObject的子类。到目前为止,我们通过使用ABCRealmString对象解决了这个问题,如下所示:
@property RLMArray<ABCRealmString> *tariffInfoLines;
ABCRealmString包含一个NSString属性(它基本上是一个包装器):
@property NSString *value;
然而,这意味着当Realm尝试映射响应以持久化数据时,它正在寻找键“值”(属性的名称)的值。它似乎期望得到类似以下的响应:
"zoneInfo": {
"tariffInfoLines": [
{
"value": "In this city you pay per minute."
},
]
}
在项目中,我们让它适用于以下结构:
"userOptions": [
{
"wantsEmailNotifications": true,
"wantsPushNotifications": false
},
]
这有一个数组,其中的对象具有Realm可以映射到的清晰键值对。 zoneInfo结构似乎是我们唯一一个包含值集的数组,而不是在对象内部或有任何键。
如果有人能够对此有所了解,可以考虑使用Realm是否可行,或者是否需要更改API以匹配Realm可以映射的结构。
答案 0 :(得分:34)
来自github issue响应的交叉发布:尽管此示例演示了如何在Realm模型上存储平面字符串数组,但您可以扩展此模式以存储从整数数组到本机Swift枚举的任何内容。基本上任何可以映射到Realm中可表示类型的东西。
class RealmString: Object {
dynamic var stringValue = ""
}
class Person: Object {
var nicknames: [String] {
get {
return _backingNickNames.map { $0.stringValue }
}
set {
_backingNickNames.removeAll()
_backingNickNames.appendContentsOf(newValue.map({ RealmString(value: [$0]) }))
}
}
let _backingNickNames = List<RealmString>()
override static func ignoredProperties() -> [String] {
return ["nicknames"]
}
}
// Usage...
let realm = try! Realm()
try! realm.write {
let person = Person()
person.nicknames = ["John", "Johnny"]
realm.add(person)
}
for person in realm.objects(Person) {
print("Person's nicknames: \(person.nicknames)")
}
// Prints:
// Person's nicknames: ["John", "Johnny"]
答案 1 :(得分:6)
更新(以前的大部分答案都不再正确):
现在,您可以直接在RLMArrays或Lists中存储基本类型或其可空对应项(更具体地说:布尔值,整数和浮点数类型,字符串,日期和数据)。如果要定义此类原始值的列表,则不再需要定义繁琐的单字段包装器对象。相反,您可以自己存储原始值。
原始值列表与包含对象的列表的工作方式大致相同,如下面的示例演示Swift:
class Student : Object {
@objc dynamic var name: String = ""
let testScores = List<Int>()
}
// Retrieve a student.
let realm = try! Realm()
let bob = realm.objects(Student.self).filter("name = 'Bob'").first!
// Give him a few test scores, and then print his average score.
try! realm.write {
bob.testScores.removeAll()
bob.testScores.append(94)
bob.testScores.append(89)
bob.testScores.append(96)
}
print("\(bob.testScores.average()!)") // 93.0
Realm支持的所有其他语言也支持基元类型列表。
答案 2 :(得分:3)
对于Swift 3.0,这里是更改(在我的情况下,当我切换到swift 3.0时,Xcode 8编译器没有提供自动修复,所以我有一些痛苦要解决它)。
_backingNickNames.append(objectsIn: newValue.map { RealmString(value: [$0]) })
答案 3 :(得分:2)
RealmString
方法很好,但每次更新数值时都会得到一个新的RealmString
,如果你不清理它们,会留下大量未使用的对象
我建议使用类似的东西:
fileprivate let separator = "\u{FFFF}"
class Person: Object {
fileprivate dynamic var _nicknames: String?
var nicknames: [String] {
get { return _nicknames?.components(separatedBy: separator) ?? [] }
set { _nicknames = newValue.isEmpty ? nil : newValue.joined(separator: separator) }
}
override static func ignoredProperties() -> [String] {
return ["nicknames"]
}
}
答案 4 :(得分:-1)
extension String {
func toStringObject() -> StringObject {
return StringObject(initValue: self)
}
}
extension Sequence where Iterator.Element == String {
func toStringObjects() -> List<StringObject> {
let list = List<StringObject>()
for s in self {
list.append(s.toStringObject())
}
return list
}
}
extension Int {
func toIntObject() -> IntObject {
return IntObject(initValue: self)
}
}
extension Sequence where Iterator.Element == Int {
func toIntObjects() -> List<IntObject> {
let list = List<IntObject>()
for s in self {
list.append(s.toIntObject())
}
return list
}
}