mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-02-25 09:04:59 +01:00
Updated Saving and processing transactions (markdown)
@@ -1,4 +1,3 @@
|
||||
|
||||
To ensure deterministic state for objects in the read-only `NSManagedObjectContext`, CoreStore does not expose API's for updating and saving directly from the main context (or any other context for that matter.) Instead, you spawn *transactions* from `DataStack` instances:
|
||||
```swift
|
||||
let dataStack = self.dataStack
|
||||
@@ -16,18 +15,22 @@ CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
```
|
||||
The `commit()` method saves the changes to the persistent store. If `commit()` is not called when the transaction block completes, all changes within the transaction is discarded.
|
||||
|
||||
The examples above use `beginAsynchronous(...)`, but there are actually 3 types of transactions at you disposal: *asynchronous*, *synchronous*, and *detached*.
|
||||
The examples above use `beginAsynchronous(...)`, but there are actually 3 types of transactions at your disposal: *asynchronous*, *synchronous*, and *detached*.
|
||||
|
||||
**Asynchronous transactions** are spawned from `beginAsynchronous(...)`. This method returns immediately and executes its closure from a background serial queue:
|
||||
### Transaction types
|
||||
|
||||
#### Asynchronous transactions
|
||||
are spawned from `beginAsynchronous(...)`. This method returns immediately and executes its closure from a background serial queue:
|
||||
```swift
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
// make changes
|
||||
transaction.commit()
|
||||
}
|
||||
```
|
||||
`transaction`'s created from `beginAsynchronous(...)` are instances of `AsynchronousDataTransaction`.
|
||||
Transactions created from `beginAsynchronous(...)` are instances of `AsynchronousDataTransaction`.
|
||||
|
||||
**Synchronous transactions** are created from `beginSynchronous(...)`. While the syntax is similar to its asynchronous counterpart, `beginSynchronous(...)` waits for its transaction block to complete before returning:
|
||||
#### Synchronous transactions
|
||||
are created from `beginSynchronous(...)`. While the syntax is similar to its asynchronous counterpart, `beginSynchronous(...)` waits for its transaction block to complete before returning:
|
||||
```swift
|
||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
// make changes
|
||||
@@ -38,7 +41,8 @@ CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
Since `beginSynchronous(...)` technically blocks two queues (the caller's queue and the transaction's background queue), it is considered less safe as it's more prone to deadlock. Take special care that the closure does not block on any other external queues.
|
||||
|
||||
**Detached transactions** are special in that they do not enclose updates within a closure:
|
||||
#### Detached transactions
|
||||
are special in that they do not enclose updates within a closure:
|
||||
```swift
|
||||
let transaction = CoreStore.beginDetached()
|
||||
// make changes
|
||||
@@ -61,6 +65,7 @@ As the above example also shows, only detached transactions are allowed to call
|
||||
You've seen how to create transactions, but we have yet to see how to make *creates*, *updates*, and *deletes*. The 3 types of transactions above are all subclasses of `BaseDataTransaction`, which implements the methods shown below.
|
||||
|
||||
### Creating objects
|
||||
|
||||
The `create(...)` method accepts an `Into` clause which specifies the entity for the object you want to create:
|
||||
```swift
|
||||
let person = transaction.create(Into(MyPersonEntity))
|
||||
@@ -69,7 +74,7 @@ While the syntax is straightforward, CoreStore does not just naively insert a ne
|
||||
- Checks that the entity type exists in any of the transaction's parent persistent store
|
||||
- If the entity belongs to only one persistent store, a new object is inserted into that store and returned from `create(...)`
|
||||
- If the entity does not belong to any store, an assert will be triggered. **This is a programmer error and should never occur in production code.**
|
||||
- If the entity belongs to multiple stores, an assert will be triggered. **This is also a programmer error and should never occur in production code.** Normally, with Core Data you can insert an object in this state but saving the `NSManagedObjectContext` will always fail. CoreStore checks this for you at creation time where it makes sense (not during save).
|
||||
- If the entity belongs to multiple stores, an assert will be triggered. **This is also a programmer error and should never occur in production code.** Normally, with Core Data you can insert an object in this state but saving the `NSManagedObjectContext` will always fail. CoreStore checks this for you at creation time when it makes sense (not during save).
|
||||
|
||||
If the entity exists in multiple configurations, you need to provide the configuration name for the destination persistent store:
|
||||
|
||||
@@ -79,11 +84,11 @@ or if the persistent store is the auto-generated "Default" configuration, specif
|
||||
|
||||
let person = transaction.create(Into<MyPersonEntity>(nil))
|
||||
|
||||
Note that if you do explicitly specify the configuration name, CoreStore will only try to insert the created object to that particular store and will fail if that store is not found; it will not fall back to any other store the entity belongs to.
|
||||
Note that if you do explicitly specify the configuration name, CoreStore will only try to insert the created object to that particular store and will fail if that store is not found; it will not fall back to any other configuration that the entity belongs to.
|
||||
|
||||
### Updating objects
|
||||
|
||||
After creating an object from the transaction, you can simply update it's properties as normal:
|
||||
After creating an object from the transaction, you can simply update its properties as normal:
|
||||
```swift
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
let person = transaction.create(Into(MyPersonEntity))
|
||||
@@ -103,7 +108,7 @@ CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
transaction.commit()
|
||||
}
|
||||
```
|
||||
*(For more about fetching, read [[Fetching and querying]])*
|
||||
*(For more about fetching, see [Fetching and querying](#fetching-and-querying))*
|
||||
|
||||
**Do not update an instance that was not created/fetched from the transaction.** If you have a reference to the object already, use the transaction's `edit(...)` method to get an editable proxy instance for that object:
|
||||
```swift
|
||||
@@ -131,9 +136,10 @@ CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
transaction.commit()
|
||||
}
|
||||
```
|
||||
|
||||
### Deleting objects
|
||||
|
||||
Deleting an object is simpler as you can tell a transaction to delete an object directly without fetching an editable proxy (CoreStore does that for you):
|
||||
Deleting an object is simpler because you can tell a transaction to delete an object directly without fetching an editable proxy (CoreStore does that for you):
|
||||
```swift
|
||||
let john: MyPersonEntity = // ...
|
||||
|
||||
|
||||
Reference in New Issue
Block a user