class Dog: Object {
dynamic var id = ""
dynamic var name = ""
dynamic var tempVariable = ""
override static func primaryKey() -> String? { return "id" }
override static func indexedProperties() -> [String] {
return ["name"]
}
override static func ignoredProperties() -> [String] {
return ["tempVariable"]
}
}
class Person: Object {
dynamic var id = ""
dynamic var name = ""
dynamic var picture: NSData? = nil // optionals supported, 16 mb max
let dogs = List<Dog>()
override static func primaryKey() -> String? { return "id" }
override static func indexedProperties() -> [String] {
return ["name"]
}
}
- Properties can be
Bool
,Int8
,Int16
,Int32
,Int64
,Double
,Float
,String
,, andNSDate
truncated to the secondNSData
(computed properties forNSDate
recommended) - String, NSDate, NSData and Object properties can be optional
- to-many relationships are defined using
List
- optional variatns of Int, Float, Double, Bool are declared with RealmOptional
- Properties should be declared with
dynamic var
except those of typeList
orRealmOptional
- Realm object settters and getters cannot be overriden
- Note that Lists can only contain subclasses of
Object
(polymorphism is not supoorted) - No support for array properties
- Temporary variables is not reccomended (their values are set to default upon refresh/write).
class Dog: Object {
dynamic var name = ""
dynamic var age = 0
var owners: [Person] {
// Realm doesn't persist this property because it only has a getter defined
// Define "owners" as the inverse relationship to Person.dogs
return linkingObjects(Person.self, forProperty: "dogs")
}
}
- Property acess (e.g.
rex.owner.address.country
) will traverse the object graph and auto fetch each object from Realm as needed. - You can only acess methods/properties from an object on the thread on which it was created.
- To share objects between threads or re-use them between app launches a persist operation which must be done within a write transaction.
do {
let realm = try Realm()
} catch let error as NSError {
// handle error
}
- All persisted (non-ignored) properties on Object subclasses are KVO-compliant, along with the
invalidated
property on Object and List. - You cannot add an object to a Realm (with realm.add(obj) or other similar methods) while it has any registered KVO observers.
-
A new realm must be inialized per thread (with the same configuration)
-
Within a thread a cached instance is used
-
Unpersisted instances of Objects are safe to pass across threads (otherwise crash on access)
-
Re-fetching will retrieve an instance at the version of the target thread, which may differ from the originating thread that prompted the fetch.
-
On getting updates:
When you initially open a Realm, its state will be based off the most recent successful write commit, and it will remain on that version until refreshed. Realms are automatically refreshed at the start of every runloop iteration, unless Realm’s autorefresh property is set to NO. If a thread has no runloop (which is generally the case in a background thread), then Realm.refresh() must be called manually in order to advance the transaction to the most recent state.
Realms are also refreshed (on all threads) when write transactions are committed (Realm.commitWrite()).
- The observer stays active as long as a reference is held to the returned notification token.
// Observe Realm Notifications
let token = realm.addNotificationBlock { notification, realm in
viewController.updateUI()
}
// (1) Create and set properties
var myDog = Dog()
myDog.name = "Rex"
myDog.age = 10
// (2) Create a Dog object from a dictionary
let myOtherDog = Dog(value: ["name" : "Pluto", "age": 3])
// (3) Create a Dog object from an array
let myThirdDog = Dog(value: ["Fido", 5])
// Nested objects
//
// Instead of using already existing dogs...
let aPerson = Person(value: ["Jane", 30, [aDog, anotherDog]])
// ...we can create them inline
let anotherPerson = Person(value: ["Jane", 30, [["Buster", 5], ["Buddy", 6]]])
- Writes block eachother and will block a thread if multiple are in progress
// Update an object with a transaction
try! realm.write {
author.name = "Thomas Pynchon"
}
// Creating a book with the same primary key as a previously saved book
let cheeseBook = Book()
cheeseBook.title = "Cheese recipes"
cheeseBook.price = 9000
cheeseBook.id = 1
// Updating book with id = 1
try! realm.write {
realm.add(cheeseBook, update: true)
}
// Partial update
//
// Assuming a "Book" with a primary key of `1` already exists.
try! realm.write {
realm.create(Book.self, value: ["id": 1, "price": 9000.0], update: true)
// the book's `title` property will remain unchanged.
}
// Updates via KVC
let persons = realm.objects(Person)
try! realm.write {
persons.first?.setValue(true, forKeyPath: "isFirst")
// set each person's planet property to "Earth"
persons.setValue("Earth", forKeyPath: "planet") // faster than iterating/reading a List
}
// Updating on a background threads
dispatch_async(queue) {
autoreleasepool {
// Get realm and table instances for this thread
let realm = try! Realm()
// Break up the writing blocks into smaller portions
// by starting a new transaction
for idx1 in 0..<1000 {
realm.beginWrite()
// Add row via dictionary. Property order is ignored.
for idx2 in 0..<1000 {
realm.create(Person.self, value: [
"name": "\(idx1)",
"birthdate": NSDate(timeIntervalSince1970: NSTimeInterval(idx2))
])
}
// Commit the write transaction
// to make this data available to other threads
try! realm.commitWrite()
}
}
}
try! realm.write {
realm.delete(cheeseBook)
realm.deleteAll()
}
- All reads (including queries and property access) are lazy in Realm.
- The
Result
of a query is auto-updating i.e. doesn't need to be refetched - Therefore indices and counts are variable
let puppies = realm.objects(Dog).filter("age < 2")
puppies.count // => 0
try! realm.write {
realm.create(Dog.self, value: ["name": "Fido", "age": 1])
}
puppies.count // => 1
// Query using a predicate string
var tanDogs = realm.objects(Dog).filter("color = 'tan' AND name BEGINSWITH 'B'").sorted("name")
// Query using an NSPredicate
let predicate = NSPredicate(format: "color = %@ AND name BEGINSWITH %@", "tan", "B")
tanDogs = realm.objects(Dog).filter(predicate)
func setDefaultRealmForUser(username: String) {
var config = Realm.Configuration()
// Use the default directory, but replace the filename with the username
config.path = NSURL.fileURLWithPath(config.path!)
.URLByDeletingLastPathComponent?
.URLByAppendingPathComponent("\(username).realm")
.path
// Set this as the configuration used for the default Realm
Realm.Configuration.defaultConfiguration = config
}
let config = Realm.Configuration(
// Get the path to the bundled file
path: NSBundle.mainBundle().pathForResource("MyBundledData", ofType:"realm"),
// Open the file in read-only mode as application bundles are not writeable
readOnly: true)
// Open the Realm with the configuration
let realm = try! Realm(configuration: config)
// Read some data from the bundled Realm
let results = realm.objects(Dog).filter("age > 5")
let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "MyInMemoryRealm"))