Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/RxSwiftCommunity/RxRealm
RxSwift extension for RealmSwift's types
https://github.com/RxSwiftCommunity/RxRealm
database reactive realm realmswift rxswift
Last synced: about 1 month ago
JSON representation
RxSwift extension for RealmSwift's types
- Host: GitHub
- URL: https://github.com/RxSwiftCommunity/RxRealm
- Owner: RxSwiftCommunity
- License: mit
- Created: 2016-04-19T10:53:02.000Z (over 8 years ago)
- Default Branch: main
- Last Pushed: 2024-05-16T21:49:58.000Z (8 months ago)
- Last Synced: 2024-10-29T15:36:04.392Z (2 months ago)
- Topics: database, reactive, realm, realmswift, rxswift
- Language: Swift
- Homepage:
- Size: 20.7 MB
- Stars: 1,156
- Watchers: 39
- Forks: 265
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-realm - RxRealm - RxSwift extension for RealmSwift's types (Swift / <a name="swift-libs"></a>Swift Libraries and Components)
- awesome-ios-star - RxRealm - Rx wrapper for Realm's collection types. (Reactive Programming / Prototyping)
- awesome-ios-1 - RxSwiftCommunity / RxRealm
- awesome-rxswift - RxRealm
- awesome-ios - RxRealm - Rx wrapper for Realm's collection types. (Reactive Programming / Prototyping)
README
# RxRealm
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Version](https://img.shields.io/cocoapods/v/RxRealm.svg?style=flat)](http://cocoapods.org/pods/RxRealm)
[![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)
[![License](https://img.shields.io/cocoapods/l/RxRealm.svg?style=flat)](http://cocoapods.org/pods/RxRealm)
[![Platform](https://img.shields.io/cocoapods/p/RxRealm.svg?style=flat)](http://cocoapods.org/pods/RxRealm)This library is a thin wrapper around __RealmSwift__ ( [Realm Docs](https://realm.io/docs/swift/latest/) ).
**Table of contents:**
1. [Observing object collections](https://github.com/RxSwiftCommunity/RxRealm#observing-object-collections)
2. [Observing a single object](https://github.com/RxSwiftCommunity/RxRealm#observing-a-single-object)
3. [Write transactions](https://github.com/RxSwiftCommunity/RxRealm#write-transactions)
4. [Automatically binding table and collection views](https://github.com/RxSwiftCommunity/RxRealm#automatically-binding-table-and-collection-views)
5. [Example app](https://github.com/RxSwiftCommunity/RxRealm#example-app)## Observing object collections
RxRealm can be used to create `Observable`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.
##### `Observable.collection(from:synchronousStart:)`
Emits an event each time the collection changes:```swift
let realm = try! Realm()
let laps = realm.objects(Lap.self)Observable.collection(from: laps)
.map {
laps in "\(laps.count) laps"
}
.subscribe(onNext: { text in
print(text)
})
```The above prints out "X laps" each time a lap 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.
##### `Observable.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):```swift
let realm = try! Realm()
let laps = realm.objects(Lap.self)Observable.array(from: laps)
.map { array in
return array.prefix(3) //slice of first 3 items
}
.subscribe(onNext: { text in
print(text)
})
```##### `Observable.changeset(from:synchronousStart:)`
Emits every time the collection changes and provides the exact indexes that has been deleted, inserted or updated:```swift
let realm = try! Realm()
let laps = realm.objects(Lap.self)Observable.changeset(from: laps)
.subscribe(onNext: { 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)
}
})
```##### `Observable.arrayWithChangeset(from:synchronousStart:)`
Combines the result of `Observable.array(from:)` and `Observable.changeset(from:)` returning an `Observable, RealmChangeset?>````swift
let realm = try! Realm()
let laps = realm.objects(Lap.self))Observable.arrayWithChangeset(from: laps)
.subscribe(onNext: { array, changes in
if let changes = changes {
// it's an update
print(array.first)
print("deleted: \(changes.deleted)")
print("inserted: \(changes.inserted)")
print("updated: \(changes.updated)")
} else {
// it's the initial data
print(array)
}
})
```## Observing a single object
There's a separate API to make it easier to observe a single object:
```swift
Observable.from(object: ticker)
.map { ticker -> String in
return "\(ticker.ticks) ticks"
}
.bindTo(footer.rx.text)
```This API uses the [Realm object notifications](https://realm.io/news/realm-objc-swift-2.4/) under the hood to listen for changes.
This method will by default emit the object initial state as its first `next` event. You can disable this behavior by using the `emitInitialValue` parameter and setting it to `false`.
Finally you can set changes to which properties constitute an object change you'd like to observe for:
```swift
Observable.from(object: ticker, properties: ["name", "id", "family"]) ...
```## Write transactions
##### `rx.add()`
Writing objects to **existing** realm reference. You can add newly created objects to a Realm that you already have initialized:
```swift
let realm = try! Realm()
let messages = [Message("hello"), Message("world")]Observable.from(messages)
.subscribe(realm.rx.add())
```Be careful, this will retain your Realm until the `Observable` completes or errors out.
##### `Realm.rx.add()`
Writing to the default Realm. You can leave it to RxRealm to grab the default Realm on any thread your subscribe and write objects to it:
```swift
let messages = [Message("hello"), Message("world")]Observable.from(messages)
.subscribe(Realm.rx.add())
```###### `Realm.rx.add(configuration:)`
Writing 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:
```swift
var config = Realm.Configuration()
/* custom configuration settings */let messages = [Message("hello"), Message("world")]
Observable.from(messages)
.observeOn( /* you can switch threads here */ )
.subscribe(Realm.rx.add(configuration: config, onError: {elements, error in
if let elements = elements {
print("Error \(error.localizedDescription) while saving objects \(String(describing: elements))")
} else {
print("Error \(error.localizedDescription) while opening realm.")
}
}))
```If you want to create a Realm on a different thread manually, allowing you to handle errors, you can do that too:
```swift
let messages = [Message("hello"), Message("world")]Observable.from(messages)
.observeOn( /* you can switch threads here */ )
.subscribe(onNext: {messages in
let realm = try! Realm()
try! realm.write {
realm.add(messages)
}
})
```##### `rx.delete()`
Deleting object(s) from an existing realm reference:
```swift
let realm = try! Realm()
let messages = realm.objects(Message.self)
Observable.from(messages)
.subscribe(realm.rx.delete())
```Be careful, this will retain your realm until the `Observable` completes or errors out.
##### `Realm.rx.delete()`
Deleting from the object's realm automatically. You can leave it to RxRealm to grab the Realm from the first object and use it:
```swift
Observable.from(someCollectionOfPersistedObjects)
.subscribe(Realm.rx.delete())
```## Automatically binding table and collection views
RxRealm does not depend on UIKit/Cocoa and it doesn't provide built-in way to bind Realm collections to UI components.
#### a) Non-animated binding
You can use the built-in RxCocoa `bindTo(_:)` method, which will automatically drive your table view from your Realm results:
```swift
Observable.from( [Realm collection] )
.bindTo(tableView.rx.items) {tv, ip, element in
let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = element.text
return cell
}
.addDisposableTo(bag)
```#### b) Animated binding with RxRealmDataSources
The separate library [RxRealmDataSources](https://github.com/RxSwiftCommunity/RxRealmDataSources) mimics the default data sources library behavior for RxSwift.
`RxRealmDataSources` allows you to bind an observable collection of Realm objects directly to a table or collection view:
```swift
// create data source
let dataSource = RxTableViewRealmDataSource(
cellIdentifier: "Cell", cellType: PersonCell.self) {cell, ip, lap in
cell.customLabel.text = "\(ip.row). \(lap.text)"
}// RxRealm to get Observable
let realm = try! Realm()
let lapsList = realm.objects(Timer.self).first!.laps
let laps = Observable.changeset(from: lapsList)// bind to table view
laps
.bindTo(tableView.rx.realmChanges(dataSource))
.addDisposableTo(bag)
```The data source will reflect all changes via animations to the table view:
![RxRealm animated changes](assets/animatedChanges.gif)
If you want to learn more about the features beyond animating changes, check the __`RxRealmDataSources`__ [README](https://github.com/RxSwiftCommunity/RxRealmDataSources).
## Example app
To run the example project, clone the repo, and run `pod install` from the Example directory first. The app uses RxSwift, RxCocoa using RealmSwift, RxRealm to observe Results from Realm.
Further you're welcome to peak into the __RxRealmTests__ folder of the example app, which features the library's unit tests.
## Installation
This library depends on both __RxSwift__ and __RealmSwift__ 1.0+.
#### CocoaPods
RxRealm requires CocoaPods 1.1.x or higher.
RxRealm is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:
```ruby
pod "RxRealm"
```#### Carthage
To integrate RxRealm into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "RxSwiftCommunity/RxRealm"
```Run `carthage update` to build the framework and drag the built `RxRealm.framework` into your Xcode project.
#### Swift Package Manager
In your Package.swift:
```swift
let package = Package(
name: "Example",
dependencies: [
.package(url: "https://github.com/RxSwiftCommunity/RxRealm.git", from: "1.0.1")
],
targets: [
.target(name: "Example", dependencies: ["RxRealm"])
]
)
```## TODO
* Test add platforms and add compatibility for the pod
## License
This library belongs to _RxSwiftCommunity_. Maintainer is [Marin Todorov](https://github.com/icanzilb).
RxRealm is available under the MIT license. See the LICENSE file for more info.