One of the strange limitations of Realm’s Database design is that it can’t seem to easily have members of primity properties like [String] or [Int]. Fortunately, all we have to do is to encapsulate it as a StringObject or an IntObject.

Let’s say we have a User object like so:

1
2
3
4
5
import RealmSwift 
class User: Object {
dynamic var userId: String
dynamic var username: String
}

We’d like to have friendUserIds as a [String] to other UserIds. If you’ve read the documentation, it requires that collection types are of List<T:Object>. And since Object can’t be of a primitive String or Int (also others like Double, Float, etc…), we need to encapsulate by creating a utility class:

1
2
3
4
5
6
7
8
9
import RealmSwift 
class StringObject: Object {
dynamic var value: String

convenience init(initValue: String){
self.init()
value = initValue
}
}

You can do this with Int, Double Bool, etc…

1
2
3
4
5
6
7
8
import RealmSwift 
class IntObject: Object {
dynamic var value: Int
convenience init(initValue: Int){
self.init()
value = initValue
}
}

Now in our User Object we can add a List<StringObject member in. Our final code for User looks like:

1
2
3
4
5
6
import RealmSwift 
class User: Object {
dynamic var userId: String
dynamic var username: String
let friendUserIds = List<StringObject>();
}

Easy!

Manipulating List<StringObject>();

List<Object> is a let type and can’t be replaced sadly. So you’ll have to call List<Object>‘s helper methods;

1
2
3
4
5
let user = User()
user.friendUserIds.removeAll() // to removeAll

let newUserIds : [String] = "max", "john" //new set of userIds
user.friendUserIds.appendContentsOf(newUserIds.map{ StringObject(initValue: $0) })

Some Helper Extension Methods

You might want to add some Extension helpers to minimize the amount of code you write. I’ve personally added these extensions on the native String object and [String] to transform them into the StringObject type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extension String {
func toStringObject() -> StringObject {
return StringObject(stringValue: self)
}
}

extension SequenceType where Generator.Element == String {
func toStringObjects() -> List<StringObject> {
let list = List<StringObject>()
for s in self {
list.append(s.toStringObject())
}
return list
}
}

Querying with NSPredicate

Querying is a little bit odd but it’s not too hard. If you’re using NSPredicate’s API you’ll need to specify a specific property aggregate query.
For example if you want to find the Users that is a friend equal to "max" then you’ll need to do this:

1
2
3
let realm = try! Realm();
let query = try! Realm().objects(User.self).filter("ANY friendUserIds.value == %@", "max")
print(query) // this will search under the StringObjects.value