Skip to content

Instantly share code, notes, and snippets.

@Alex-Ozun
Last active July 11, 2018 10:33
Show Gist options
  • Save Alex-Ozun/8cacf3416757b2192b488f869c9df637 to your computer and use it in GitHub Desktop.
Save Alex-Ozun/8cacf3416757b2192b488f869c9df637 to your computer and use it in GitHub Desktop.
Thread safe wrapper around Realm database. iOS. Swift 4.1
public final class RealmWrapper {
private let _workerQueue = DispatchQueue(label: "RealmWrapper",
qos: .utility)
/// Creates Realm object on designated thread. This gives you oportunity to query some object in a thread-safe environment or resolve ThreadSafeReference before performing writes.
///
/// - Parameter block: accepts a newely created Realm object. which relates to a designated database thread.
public func open(_ block: @escaping (Realm?) -> Void) {
_workerQueue.async {
do {
block(try Realm())
} catch(let error) {
//TODO: consider returning error.
fatalError(error.localizedDescription)
}
}
}
/// Creates Realm object on caller's thread. It is unsafe to perform any writes on this instance of realm.
///Use it only for reads. For writes use method `open(_ block: @escaping (Realm?) -> Void)`.
///
/// - Returns: newely created Realm object
public func open() -> Realm? {
do {
let realm = try Realm()
return realm
} catch(_) {
return nil
}
}
/// Performs synchronouse write operation on provided Realm object or creates new Realm on caller's thread.
///
/// - Parameters:
/// - realm: Realm object on which to perform write. Creates new if not provided
/// - block: write operation
/// - Returns: Success of write operation
@discardableResult
public func write(toRealm realm: Realm? = nil,
block: @escaping () -> Void) -> Bool {
do {
let _realm = try realm ?? Realm()
try _realm.safeWrite {
block()
}
return true
} catch(let error) {
#if DEBUG
fatalError(error.localizedDescription)
#else
return false
#endif
}
}
public func openAndWrite(_ block: @escaping (Realm) -> Void,
completion: (() -> Void)? = nil) {
open { (realm) in
guard let realm = realm else {
completion?(false)
return
}
do {
try realm.safeWrite {
block(realm)
}
completion?(true)
} catch(let error) {
completion?(false)
}
}
}
}
extension Realm {
public func safeWrite(_ block: (() throws -> Void)) throws {
if isInWriteTransaction {
try block()
} else {
try write(block)
}
}
}
//==================EXAMPLE==========
let realmWrapper = RealmWrapper()
realmWrapper.open({ (realm) in
guard let object = realm?.object(ofType: MyObject.self,
forPrimaryKey: "123") else {
completion(false)
return
}
let isSuccess = realmWrapper.write(toRealm: realm) {
object.stringValue = "new value"
}
completion(isSuccess)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment