Skip to content

Instantly share code, notes, and snippets.

@Kleemann
Last active December 4, 2017 07:43
Show Gist options
  • Select an option

  • Save Kleemann/e4a425816157bde074b32d51440df7ab to your computer and use it in GitHub Desktop.

Select an option

Save Kleemann/e4a425816157bde074b32d51440df7ab to your computer and use it in GitHub Desktop.
//
// DatabaseWorker.swift
// Readlst
//
// Created by Mads Kleemann on 04/08/2017.
// Copyright (c) 2017 Readlst. All rights reserved.
//
import UIKit
import RealmSwift
class DatabaseWorker {
fileprivate let defaultTimeout = 2.5
func save<T: Object>(objects: [T], updateIfExsists: Bool = true, completion: (() -> Void)? = .none) throws {
let semaphore = DispatchSemaphore(value: 0)
do {
let realm = try Realm()
try realm.write {
realm.add(objects, update: updateIfExsists)
semaphore.signal()
}
_ = semaphore.wait(timeout: .now() + defaultTimeout)
completion?()
} catch let error {
throw error
}
}
func getObjects<T: Object>(withPredicate predicate: NSPredicate? = .none) -> [T] {
let objects: Results<T>? = getList(withPredicate: predicate)
return objects == .none ? [] : Array(objects!)
}
func getObject<T: Object>(withPredicate predicate: NSPredicate) -> T? {
let object: T? = getList(withPredicate: predicate)?.first
return object
}
func delete<T: Object>(ofType type: T.Type, withPredicate predicate: NSPredicate? = .none, completion: (() -> Void)? = .none) throws {
guard let objectsToDelete: Results<T> = self.getList(withPredicate: predicate), objectsToDelete.count > 0 else {
//We dont have any objects of the type so we just complete
completion?()
return
}
let semaphore = DispatchSemaphore(value: 0)
do {
let realm = try Realm()
try realm.write {
realm.delete(objectsToDelete)
semaphore.signal()
}
_ = semaphore.wait(timeout: .now() + defaultTimeout)
completion?()
} catch let error {
throw error
}
}
func delete(_ object:Object) throws {
do {
let realm = try Realm()
try realm.write {
realm.delete(object)
}
} catch let error {
throw error
}
}
func replaceAllObjects<T: Object>(ofType: T.Type, withObjects newObjects: [T], completion: (() -> Void)? = .none) throws {
guard let objectsInDatabase: Results<T> = getList(), objectsInDatabase.count > 0 else {
//We dont have any object in the database of type, just save the new objects
do {
try save(objects: newObjects, completion: completion)
} catch let error {
throw error
}
return
}
let objectsToUpdate = newObjects.filter { objectsInDatabase.contains($0) }
let objectsToAdd = newObjects.filter { !objectsInDatabase.contains($0) }
let objectsToDelete = objectsInDatabase.filter { !newObjects.contains($0) }
let semaphore = DispatchSemaphore(value: 0)
do {
let realm = try Realm()
try realm.write {
realm.add(objectsToUpdate, update: true)
realm.add(objectsToAdd)
realm.delete(objectsToDelete)
semaphore.signal()
}
_ = semaphore.wait(timeout: .now() + defaultTimeout)
completion?()
} catch let error {
throw error
}
}
func addNotification<T:Object>(forObject objectType: T.Type,
withPredicate predicate: NSPredicate? = .none,
sortedBy sorting: (sortKey: String, ascending: Bool)? = .none,
andBlock block: @escaping (RealmCollectionChange<Results<T>>) -> Void) -> NotificationToken? {
var objectList: Results<T>? = getList(withPredicate: predicate)
if let sorting = sorting {
objectList = objectList?.sorted(byKeyPath: sorting.sortKey, ascending: sorting.ascending)
}
return objectList?.observe({ (changes) in
block(changes)
})
}
func write(_ block: () -> Void) throws {
do {
let realm = try Realm()
try realm.write {
block()
}
} catch let error {
throw error
}
}
fileprivate func getList<T: Object>(withPredicate predicate: NSPredicate? = .none) -> Results<T>? {
let realm = try? Realm()
var objects: Results<T>? = .none
if let p = predicate {
objects = realm?.objects(T.self).filter(p)
} else {
objects = realm?.objects(T.self)
}
return objects
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment