You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CoreDataRepository is a reactive library (Combine) for using CoreData on a background queue. It features endpoints for CRUD, batch, fetch, and aggregate operations. Also, it offers a stream like subscription for fetch and read.
8
+
CoreDataRepository is a library for using CoreData on a background queue. It features endpoints for CRUD, batch, fetch, and aggregate operations. Also, it offers a stream like subscription for fetch and read.
8
9
9
10
Since ```NSManagedObject```s are not thread safe, a value type model must exist for each ```NSMangaedObject``` subclass.
10
11
@@ -14,8 +15,9 @@ Since ```NSManagedObject```s are not thread safe, a value type model must exist
14
15
CoreData is a great framework for local persistence on Apple's platforms. However, it can be tempting to create strong dependencies on it throughout an app. Even worse, the `viewContext` runs on the main `DispatchQueue` along with the UI. Even fetching data from the store can be enough to cause performance problems.
15
16
16
17
The goals of `CoreDataRepository` are:
18
+
17
19
- Ease isolation of `CoreData` related code away from the rest of the app.
18
-
- Improve ergonomics by providing an asynchronous API with `Combine`.
20
+
- Improve ergonomics by providing an asynchronous API.
19
21
- Improve usability of private contexts to relieve load from the main `DispatchQueue`.
20
22
- Make local persistence with `CoreData` feel more 'Swift-like' by allowing the model layer to use value types.
21
23
@@ -33,9 +35,11 @@ To give some weight to this idea, here's a quote from the Q&A portion of [this](
33
35
## Basic Usage
34
36
35
37
### Model Bridging
38
+
36
39
There are two protocols that handle bridging between the value type and managed models.
let publisher: AnyPublisher<(success: [Movie], failed: [Movie]), Never> = repository.create(movies)
237
-
_= publisher
238
-
.subscribe(on: backgroundQueue)
239
-
.receive(on: mainQueue)
240
-
.sink(
241
-
receiveCompletion: { completion in
242
-
switch completion {
243
-
case .finished:
244
-
os_log("Finished inserting A LOT of movies")
245
-
default:
246
-
fatalError("Failed to insert a lot of movies")
247
-
}
248
-
},
249
-
receiveValue: { createdMovies in
250
-
os_log("Created these movies: \(createdMovies)")
251
-
}
252
-
)_
196
+
let result: (success: [Movie], failed: [Movie]) =await repository.create(movies)
197
+
os_log("Created these movies: \(result.success)")
198
+
os_log("Failed to create these movies: \(result.failed)")
253
199
```
254
200
255
-
256
201
## TODO
257
-
- Add a subscription feature for aggregate functions
258
202
203
+
- Add a subscription feature for aggregate functions
204
+
- Migrate subscription endpoints to AsyncSequence instead of Publisher
205
+
- Simplify model protocols (require only one protocol for the value type)
206
+
- Allow older platform support by working around the newer variants of `NSManagedObjectContext.perform` and `NSManagedObjectContext.performAndWait`
259
207
260
208
## Contributing
209
+
261
210
I welcome any feedback or contributions. It's probably best to create an issue where any possible changes can be discussed before doing the work and creating a PR.
211
+
212
+
The above [TODO](#todo) section is a good place to start if you would like to contribute but don't already have a change in mind.
0 commit comments