Realm
Why Realm so fast
Traditional ORM/Core Data/etc
Workflow:
- translate the request into a series of SQL
- create a database connection (if it hasn’t already been created)
- send it to the disk, perform the query, read all the data from the rows that match the query
- bring all of that into memory (that’s the memory allocation)
zero‑copy architecture
The are two tricks I can see in realm to achieve Zero-Copy.
- Properties are accessors
All dynamic properties in Realm Object classes are just accessors to some memory addresses. They don’t store values by themselves. (This is the reason why Realm Objects are auto-updating objects also) - The database file is always memory‑mapped
Realm accesses any offset in the file as if it were already in memory even though it’s not – it’s virtual memory
Why can’t Realm objects be passed across thread boundaries?
Since Realm is based upon a zero‑copy architecture, all objects are live and auto‑updating. If Realm allowed objects to be passed across threads, Realm would not be able to ensure data consistency because various threads could be attempting to change an object’s data at undetermined points in time then the data could become inconsistent.
Auto-Updating Objects & Queries
let puppies = realm.objects(Dog).filter("age == 2") puppies.count // = 0 because no dogs have been added to the Realm yet let myDog = Dog() myDog.name = "Rex" myDog.age = 1 try! realm.write { realm.add(myDog) } puppies.count // = 1 updated in real-time
Getting Notified When Realm Data Changes
let stepCounter = StepCounter() let realm = try! Realm() try! realm.write { realm.add(stepCounter) } var token : NotificationToken? token = stepCounter.observe { change in switch change { case .change(let properties): for property in properties { print (property.name) } case .error(let error): print("An error occurred: \(error)") case .deleted: print("The object was deleted.") } }
Codable + Realm
enum UserProperty: String { case id, name, email } class User: Object, Codable { @objc dynamic var id:Int = 0 @objc dynamic var name:String? @objc dynamic var email:String? private enum CodingKeys: String, CodingKey { case id, name, email = "mail" } override static func primaryKey() -> String? { return UserProperty.id.rawValue } //avoid realm storing properties override static func ignoredProperties() -> [String] { return [UserProperty.email] } //when type of data you received from server not match with //type you declared required convenience init(from decoder: Decoder) throws { self.init() let container = try decoder.container(keyedBy: CodingKeys.self) id = try Int(container.decode(String.self, forKey: .id))! name = try? container.decodeIfPresent(String.self, forKey: .name) email = try? container.decodeIfPresent(String.self, forKey: .email) } }
Fetch data from server with Alamofire and store to Realm database
extension JSONDecoder { func decodeResponse<T: Decodable>(from response: DataResponse<Data>) -> T? { guard response.error == nil, let responseData = response.data else { return nil } do { let item = try decode(T.self, from: responseData) return item } catch { print(error) return nil } } } func fetchData(callback: @escaping (Bool)-> Void){ Alamofire.request("url").responseData(completionHandler: {response in if let users :[User] = JSONDecoder().decodeResponse(from: response){ let realm = try! Realm() try! realm.write { realm.add(users, update: .all) } } }) }

A nature, universe, science, music, love lover