https://github.com/ABridoux/SafeFetching
DSL to build predicates and requests for CoreData fetching
https://github.com/ABridoux/SafeFetching
coredata fetching predicate swift
Last synced: 7 months ago
JSON representation
DSL to build predicates and requests for CoreData fetching
- Host: GitHub
- URL: https://github.com/ABridoux/SafeFetching
- Owner: ABridoux
- License: mit
- Created: 2021-10-23T10:47:27.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-10-04T15:47:19.000Z (over 3 years ago)
- Last Synced: 2024-11-13T19:14:32.925Z (over 1 year ago)
- Topics: coredata, fetching, predicate, swift
- Language: Swift
- Homepage:
- Size: 412 KB
- Stars: 21
- Watchers: 3
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: License
Awesome Lists containing this project
README
# SafeFetching
This library offers a DSL (Domain Specific Language) to safely build predicates and requests to fetch a CoreData store.
The documentation is built with docC. You can [read it online](https://abridoux.github.io/SafeFetching/documentation/safefetching/) or locally by running *Product* → *Build Documentation* or hitting **⇧⌃⌘D**.
## Convenient and Safe Fetching
The library requires to manually define the entity class. Then the macro `FetchableManagedObject` can be used.
```swift
@FetchableManagedObject
final class User: NSManagedObject {
@NSManaged var score = 0.0
@NSManaged var name: String? = ""
}
```
This makes `User` conform to `Fetchable` and ready to be used with the SafeFetching API.
Then it's possible to use the DSL to build a request. The last step can either get the built request as `NSFetchRequest` or execute the request in the provided context.
```swift
User.request()
.all(after: 10)
.where { $0.score >= 15 || $0.name != "Joe" }
.sorted(by: .ascending(\.score), .descending(\.name))
.setting(\.returnsDistinctResults, to: true)
.nsValue // returns NSFetchRequest
```
```swift
User.request()
.all(after: 10)
.where { $0.score >= 15 || $0.name != "Joe" }
.sorted(by: .ascending(\.score), .descending(\.name))
.setting(\.returnsDistinctResults, to: true)
.fetch(in: context) // returns [User]
```
Advanced `NSPredicate` operators are also available like `BEGINSWITH` (`hasPrefix`).
```swift
User.request()
.all()
.where { $0.name.hasPrefix("Do", options: .caseInsensitive) }
.nsValue
```
More about predicates in the [documentation](https://abridoux.github.io/SafeFetching/documentation/safefetching/build-predicates).
### Convenience for NS types
The library also offers convenience functions to set a predicate of a `NSFetchRequest`.
```swift
request.predicate = .safe(on: User.self) { $0.score.isIn(10...20 }
// or
request.predicate = .safe(on: User.self) { (10...20).contains($0.score) }
```
## `NSPredicate`, `Predicate`
Why not using the `Predicate` macro? Two reasons.
- It works only with SwiftData as of today (so iOS 17+, macOS 14+ ...). It doesn't work with CoreData.
- It doesn't support everything that `NSPredicate` does when fetching a CoreData store.
Meanwhile, `NSPredicate` requires to write everything in a `String`, which is very error-prone.
Whereas this library tries to cover three objectives:
1. Use compiler-checking to evaluate predicates and avoid runtime errors.
2. Writing a request and especially a predicate should feel as natural as possible in Swift.
3. No feature of NSPredicate to fetch a CoreData store should be left behind.