add swiftUI code
This commit is contained in:
+111
@@ -0,0 +1,111 @@
|
||||
# ``GRDB/DatabaseRegionObservation``
|
||||
|
||||
`DatabaseRegionObservation` tracks changes in a database region, and notifies impactful transactions.
|
||||
|
||||
## Overview
|
||||
|
||||
`DatabaseRegionObservation` tracks insertions, updates, and deletions that impact the tracked region, whether performed with raw SQL, or <doc:QueryInterface>. This includes indirect changes triggered by [foreign keys actions](https://www.sqlite.org/foreignkeys.html#fk_actions) or [SQL triggers](https://www.sqlite.org/lang_createtrigger.html).
|
||||
|
||||
See <doc:GRDB/DatabaseRegionObservation#Dealing-with-Undetected-Changes> below for the list of exceptions.
|
||||
|
||||
`DatabaseRegionObservation` calls your application right after changes have been committed in the database, and before any other thread had any opportunity to perform further changes. *This is a pretty strong guarantee, that most applications do not really need.* Instead, most applications prefer to be notified with fresh values: make sure you check ``ValueObservation`` before using `DatabaseRegionObservation`.
|
||||
|
||||
## DatabaseRegionObservation Usage
|
||||
|
||||
Create a `DatabaseRegionObservation` with one or several requests to track:
|
||||
|
||||
```swift
|
||||
// Tracks the full player table
|
||||
let observation = DatabaseRegionObservation(tracking: Player.all())
|
||||
```
|
||||
|
||||
Then start the observation from a ``DatabaseQueue`` or ``DatabasePool``:
|
||||
|
||||
```swift
|
||||
let cancellable = try observation.start(in: dbQueue) { error in
|
||||
// Handle error
|
||||
} onChange: { (db: Database) in
|
||||
print("Players were changed")
|
||||
}
|
||||
```
|
||||
|
||||
Enjoy the changes notifications:
|
||||
|
||||
```swift
|
||||
try dbQueue.write { db in
|
||||
try Player(name: "Arthur").insert(db)
|
||||
}
|
||||
// Prints "Players were changed"
|
||||
```
|
||||
|
||||
You stop the observation by calling the ``DatabaseCancellable/cancel()`` method on the object returned by the `start` method. Cancellation is automatic when the cancellable is deallocated:
|
||||
|
||||
```swift
|
||||
cancellable.cancel()
|
||||
```
|
||||
|
||||
`DatabaseRegionObservation` can also be turned into a Combine publisher, or an RxSwift observable (see the companion library [RxGRDB](https://github.com/RxSwiftCommunity/RxGRDB)):
|
||||
|
||||
```swift
|
||||
let cancellable = observation.publisher(in: dbQueue).sink { completion in
|
||||
// Handle completion
|
||||
} receiveValue: { (db: Database) in
|
||||
print("Players were changed")
|
||||
}
|
||||
```
|
||||
|
||||
You can feed `DatabaseRegionObservation` with any type that conforms to the ``DatabaseRegionConvertible`` protocol: ``FetchRequest``, ``DatabaseRegion``, ``Table``, etc. For example:
|
||||
|
||||
```swift
|
||||
// Observe the score column of the 'player' table
|
||||
let observation = DatabaseRegionObservation(
|
||||
tracking: Player.select(Column("score")))
|
||||
|
||||
// Observe the 'score' column of the 'player' table
|
||||
let observation = DatabaseRegionObservation(
|
||||
tracking: SQLRequest("SELECT score FROM player"))
|
||||
|
||||
// Observe both the 'player' and 'team' tables
|
||||
let observation = DatabaseRegionObservation(
|
||||
tracking: Table("player"), Table("team"))
|
||||
|
||||
// Observe the full database
|
||||
let observation = DatabaseRegionObservation(
|
||||
tracking: .fullDatabase)
|
||||
```
|
||||
|
||||
## Dealing with Undetected Changes
|
||||
|
||||
`DatabaseRegionObservation` will not notify impactful transactions whenever the database is modified in an undetectable way:
|
||||
|
||||
- Changes performed by external database connections.
|
||||
- Changes performed by SQLite statements that are not compiled and executed by GRDB.
|
||||
- Changes to the database schema, changes to internal system tables such as `sqlite_master`.
|
||||
- Changes to [`WITHOUT ROWID`](https://www.sqlite.org/withoutrowid.html) tables.
|
||||
|
||||
To have observations notify such undetected changes, applications can take explicit action: call the ``Database/notifyChanges(in:)`` `Database` method from a write transaction:
|
||||
|
||||
```swift
|
||||
try dbQueue.write { db in
|
||||
// Notify observations that some changes were performed in the database
|
||||
try db.notifyChanges(in: .fullDatabase)
|
||||
|
||||
// Notify observations that some changes were performed in the player table
|
||||
try db.notifyChanges(in: Player.all())
|
||||
|
||||
// Equivalent alternative
|
||||
try db.notifyChanges(in: Table("player"))
|
||||
}
|
||||
```
|
||||
|
||||
## Topics
|
||||
|
||||
### Creating DatabaseRegionObservation
|
||||
|
||||
- ``init(tracking:)-5ldbe``
|
||||
- ``init(tracking:)-2nqjd``
|
||||
|
||||
### Observing Database Transactions
|
||||
|
||||
- ``publisher(in:)``
|
||||
- ``start(in:onError:onChange:)``
|
||||
Reference in New Issue
Block a user