CombineRealm
This library is a thin wrapper around RealmSwift (Realm Docs), inspired by the RxSwift Community's RxRealm library.
Usage
Table of contents:
- Observing object collections
- Observing a single object
- Observing a realm instance
- Write transactions
- Delete transactions
- Example app
Observing object collections
CombineRealm can be used to create Publisher
s from objects of type Results
, List
, LinkingObjects
or AnyRealmCollection
. These types are typically used to load and observe object collections from the Realm Mobile Database.
RealmPublishers.collection(from:synchronousStart:)
Emits an event each time the collection changes:
let realm = try! Realm()
let colors = realm.objects(Color.self)
RealmPublishers.collection(from: colors)
.map { colors in "colors: \(colors.count)" }
.sink(receiveCompletion: { _ in
print("Completed")
}, receiveValue: { result in
print(result)
})
The above prints out "colors: X" each time a Color
instance is added or removed from the database. If you set synchronousStart
to true
(the default value), the first element will be emitted synchronously - e.g. when you're binding UI it might not be possible for an asynchronous notification to come through.
RealmPublishers.array(from:synchronousStart:)
Upon each change fetches a snapshot of the Realm collection and converts it to an array value (for example if you want to use array methods on the collection):
let realm = try! Realm()
let colors = realm.objects(Color.self)
RealmPublishers.array(from: colors)
.map { colors in colors.prefix(3) }
.sink(receiveCompletion: { _ in
print("Completed")
}, receiveValue: { colors in
print(colors)
})
RealmPublishers.changeset(from:synchronousStart:)
Emits every time the collection changes and provides the exact indexes that have been deleted, inserted or updated along with the appropriate AnyRealmCollection<T>
value:
let realm = try! Realm()
let colors = realm.objects(Color.self)
RealmPublishers.changeset(from: colors)
.sink(receiveCompletion: { _ in
print("Completed")
}, receiveValue: { results, changes in
if let changes = changes {
// it's an update
print(results)
print("deleted: \(changes.deleted)")
print("inserted: \(changes.inserted)")
print("updated: \(changes.updated)")
} else {
// it's the initial data
print(results)
}
})
RealmPublishers.arrayWithChangeset(from:synchronousStart:)
Emits every time the collection changes and provides the exact indexes that have been deleted, inserted or updated along with the Array<T>
value:
let realm = try! Realm()
let colors = realm.objects(Color.self))
RealmPublishers.arrayWithChangeset(from: colors)
.sink(receiveCompletion: { _ in
print("Completed")
}, receiveValue: { array, changes in
if let changes = changes {
// it's an update
print(array)
print("deleted: \(changes.deleted)")
print("inserted: \(changes.inserted)")
print("updated: \(changes.updated)")
} else {
// it's the initial data
print(array)
}
})
Observing a single object
RealmPublishers.from(object:emitInitialValue:properties:)
Emits every time any of the properties of the observed object change.
It will by default emit the object's initial state as its first value. You can disable this behavior by using the emitInitialValue
parameter and setting it to false
.
RealmPublishers.from(object: color)
.sink(receiveCompletion: { _ in
print("Completed")
}) { color in
print(color)
}
You can set which property changes you'd like to observe:
Observable.from(object: ticker, properties: ["red", "green", "blue"])
Observing a realm instance
RealmPublishers.from(realm:)
Emits every time the realm changes: any create & update & delete operation happens in it. It provides the realm instance along with the realm change notification.
let realm = try! Realm()
RealmPublishers.from(realm: realm)
.sink(receiveCompletion: { _ in
print("Completed")
}) { realm, notification in
print("Something happened!")
}
Write transactions
addToRealm()
Writes object(s) to the default Realm: Realm(configuration: .defaultConfiguration)
.
let realm = try! Realm()
let colors = realm.objects(Color.self))
RealmPublishers.array(from: colors)
.addToRealm()
addToRealm(configuration:updatePolicy:onError:)
Writes object(s) to a custom Realm. If you want to switch threads and not use the default Realm, provide a Realm.Configuration
. You an also provide an error handler for the observer to be called if either creating the realm reference or the write transaction raise an error:
NOTE: All 3 arguments are optional, check the function definition for the default values
let realm = try! Realm()
let colors = realm.objects(Color.self))
RealmPublishers.array(from: colors)
.addToRealm(configuration: .defaultCOnfiguration, updatePolicy: .error, onError: {
print($0)
})
Delete transactions
deleteFromRealm()
Deletes object(s) from the object(s)'s realm:
let realm = try! Realm()
let colors = realm.objects(Color.self))
RealmPublishers.array(from: colors)
.deleteFromRealm()
deleteFromRealm(onError:)
Deletes object(s) from the object(s)'s realm. You an also provide an error handler for the observer to be called if either creating the realm reference or the write transaction raise an error:
let realm = try! Realm()
let colors = realm.objects(Color.self))
RealmPublishers.array(from: colors)
.deleteFromRealm(onError: {
print($0)
})
Example app
To run the example project, clone the repo, navigate to the Example folder and open the Example.xcodeproj
file.
To ensure that you're using the latest version of CombineRealm, in Xcode select Update to Latest Package Versions
in the File/Swift Packages/Add Package Dependency...
menu.
The app uses CombineRealm to observe changes in and write to Realm.
Testing
To inspect the library's Unit tests, check out the files in Tests/CombineRealmTests
.
To run the tests, go to the root directory of the repo and run the command:
swift test
Installation
CocoaPods
Add the following line to your Podfile and run pod install
:
pod 'Combine-Realm'
Since import statements in Xcode can't contain dashes, the correct way to import the library is:
import Combine_Realm
Swift Package Manager
- In Xcode select
File/Swift Packages/Add Package Dependency...
- Paste
https://github.com/istvan-kreisz/CombineRealm.git
into the repository URL textfield.
Future ideas
- Add CI tests
- Add Carthage support
- Your ideas?
Author
Istvan Kreisz
License
CombineReachability is available under the MIT license. See the LICENSE file for more info.