I'm using Realm in a App and I'm trying to abstract much as possible so that in the future I can swap database providers without too much change.
This pattern has worked well although I'm concerned about the following.
Are there any better design patterns for my purpose ?
public struct BookDataLayer: BookDataLayerProvider {
func isBookAvailable(bookIdentifier: String) throws -> Bool {
let database = try getDatabase()
return !database.objects(Book).filter("identifier = %@", bookIdentifier).isEmpty
}
func createOrUpdateBook(bookIdentifier: String, sortIndex: Int) throws {
let book = Book()
Book.bookIdentifier = bookIdentifier
Book.sortIndex = sortIndex
try create(book, update: true)
}}
protocol BookDataLayerProvider : DataAccessLayer {
func isBookAvailable(bookIdentifier: String) throws -> Bool
func createOrUpdateBook(bookIdentifier: String, sortIndex: Int) throws n}
extension DataAccessLayer {
func getDatabase() throws -> Realm {
do {
let realm = try Realm()
// Advance the transaction to the most recent state
realm.refresh()
return realm
} catch {
throw DataAccessError.DatastoreConnectionError
}
}
func create(object: Object, update: Bool = false) throws {
let database = try self.getDatabase()
do {
database.beginWrite()
database.add(object, update: update)
// Commit the write transaction
// to make this data available to other threads
try database.commitWrite()
} catch {
throw DataAccessError.InsertError
}
}}
// Usage
let bookDataLayer = BookDataLayer()
bookDataLayer.isBookAvailable("4557788")
bookDataLayer.createOrUpdateBook("45578899", 10)
That's a completely solid design pattern. It's pretty common for developers to abstract the data layer APIs way from their code in case they need to switch it out.
In response to your questions:
Realm
object instances are internally cached, so you can easily call let realm = try! Realm()
multiple times with very little overhead.refresh()
on the Realm instance every time you use it. Realm instances on the main thread are automatically refreshed on each iteration of the run loop, so you only need to call refresh()
if you're expecting changes on a background thread, or need to access changes before the current run loop has completed.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With