Description
The RSRealmHelper library is a class helper to work with Realm database removing all boilerplate when setting your database. This library configures all Realm database to work with crypto, saving a crypto key on keychain access using a KeyChainAccess library. It allows you to use multiple realm files to isolate data by user and create a clone connection to perform a thread safe execution.
Example
To run the example project, first clone the repo and run pod install
from the Example directory.
Requirements
Installation
RSRealmHelper is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'RSRealmHelper'
Usage
You can use the library directly, without initial setup.
Entities
Create your own entities following the instructions on Realm Documentation like EmployeeRealm
import RealmSwift
final class EmployeeRealm: Object {
@objc dynamic var id = Int()
@objc dynamic var name = String()
override static func primaryKey() -> String? {
return "id"
}
}
RealmHelper Instances
The RealmHelper Instances allows you to create an instance of realm to specific purposes. You can create a default, custom or inMemory instance, but only default and custom instances use crypto.
Create a RealmHelper on your local data manager class to manage objects on database.
You can create a default instance of database.
let realmHelper = RealmHelper()
let realmHelper = RealmHelper(realmInstance: .default)
With custom type you can separate the user data on a specific file, isolated from others.
let instanceName = "user_123"
let realmInstance = RealmFactory.Instance.custom(name: instanceName)
let realmHelper = RealmHelper(realmInstance: realmInstance)
Or you can create your database inMemory for tests purposes.
let realmHelper = RealmHelper(realmInstance: .inMemory)
Save / Update objects
You can save or update your entity using a RealmHelper by simply calling save
or update
functions with the entity as a parameter. But to update your entity, it needs to implement a primary key and not be attached to realm yet
let employee = EmployeeRealm()
try! realmHelper.save(employee)
try! realmHelper.update(employee)
If you need to increment your identifier, which usually is the primary key property, you need to call a function with the name of the parameter you need to increase.
let employee = EmployeeRealm()
try! realmHelper.save(employee, incrementProperty: "id")
To update an attached realm object, you need to open a write block and update the properties.
Write block sends an instance of realm in case you need to create something in particular.
let employee = EmployeeRealm()
try! realmHelper.save(employee)
try! realmHelper.writeInRealm { realm in
employee.name = "new name"
}
Fetch / Count objects
RealmHelper provides some functions to help you write a more redable code, because it works with generics and type inference.
// Count employees in database
let count = realmHelper.count(ofType: EmployeeRealm.self)
// get all employees saved on database
let employeeList: [EmployeeRealm] = realmHelper.findAll()
// Get first employee saved on database
let employee: EmployeeRealm? = realmHelper.findFirst()
// Create a query
let predicate = NSPredicate(format: "id == %d", id)
// Count all employees that matches with your query
let count = realmHelper.count(withPredicate: predicate, ofType: EmployeeRealm.self)
// get all employees that matches with your query
let employeeList: [EmployeeRealm] = realmHelper.findAll(withPredicate: predicate)
// Get first employee that matches with your query
let employee: EmployeeRealm? = realmHelper.findFirst(withPredicate: predicate)
Delete objects
RealmHelper provides two ways to delete objects, a simple delete and a cascade delete that deletes elements and their children.
To simple delete you can call the delete function.
// Delete a single element
let employee = EmployeeRealm()
try! realmHelper.delete(employee)
// Delete a list of elements
let employeeList: [EmployeeRealm] = [EmployeeRealm(), EmployeeRealm()]
realmHelper.delete(elements: employeeList)
// Delete all elements in table
try! realmHelper.deleteAll(type: EmployeeRealm.self)
If you need to delete entities using a cascade method, you need to implement the CascadeDeletable
protocol in your entity to map the properties that need to be deleted together:
final class CompanyRealm: Object {
@objc dynamic var id = Int()
@objc dynamic var name = String()
var employeeList = List<EmployeeRealm>()
}
// MARK: - CascadeDeletable
extension CompanyRealm: CascadeDeletable {
var objectsForCascadeDelete: [Object] {
var objects: [Object] = []
objects.append(contentsOf: employeeList.toArray())
return objects
}
static var typesForCascadeDelete: [Object.Type] {
return [EmployeeRealm.self]
}
}
Then you need to call the function cascadingDelete
instead the delete
function.
try! realmHelper.cascadingDelete(company)
If you need to delete all database you can call
try! realmHelper.clearDatabase()
Thread safe
To call RealmHelper's functions in diferent threads using the same helper you need to clone the helper instance before your function calls.
DispatchQueue.main.async {
let threadSafeRealmHelper = self.realmHelper.clone()
let companyList: [CompanyRealm] = threadSafeRealmHelper.findAll()
print("Thread safe sample: \(companyList)")
}
Debug
Set the property RealmFactory.enableDebug
to enable / disable the debug messages
RealmFactory.enableDebug = true
Migration
To perform a Realm migration in your database you need to add a key in a project info.plist with name DATABASE_SCHEMA_VERSION
and the numeric value of your database schema version.
Create a class that implements the RealmMigrator
protocol:
class MyRealmMigrator: RealmMigrator {
func execute(migration: Migration, realmInstance: RealmFactory.Instance, oldVersion: UInt64, currentVersion: UInt64) {
}
}
You must set your new class, which implements a RealmMigrator
protocol, on RealmFactory
class.
RealmFactory.realmMigrator = MyRealmMigrator()
Credits
RSRealmHelper is owned and maintained by the redspark
Contributors
Marcus Costa - [email protected] Andre M. Della Torre - [email protected]
License
RSRealmHelper is available under the MIT license. See the LICENSE file for more info.