{"id":13995008,"url":"https://github.com/ABridoux/SafeFetching","last_synced_at":"2025-07-22T21:31:51.708Z","repository":{"id":38192988,"uuid":"420385030","full_name":"ABridoux/SafeFetching","owner":"ABridoux","description":"DSL to build predicates and requests for CoreData fetching","archived":false,"fork":false,"pushed_at":"2022-10-04T15:47:19.000Z","size":422,"stargazers_count":21,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-13T19:14:32.925Z","etag":null,"topics":["coredata","fetching","predicate","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ABridoux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-23T10:47:27.000Z","updated_at":"2024-10-16T09:42:51.000Z","dependencies_parsed_at":"2023-01-19T05:15:54.663Z","dependency_job_id":null,"html_url":"https://github.com/ABridoux/SafeFetching","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ABridoux%2FSafeFetching","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ABridoux%2FSafeFetching/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ABridoux%2FSafeFetching/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ABridoux%2FSafeFetching/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ABridoux","download_url":"https://codeload.github.com/ABridoux/SafeFetching/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227177735,"owners_count":17743151,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coredata","fetching","predicate","swift"],"created_at":"2024-08-09T14:03:12.743Z","updated_at":"2025-07-22T21:31:51.696Z","avatar_url":"https://github.com/ABridoux.png","language":"Swift","readme":"# SafeFetching\n\nThis library offers a DSL (Domain Specific Language) to safely build predicates and requests to fetch a CoreData store.\n\nThe 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**.\n\n## Convenient and Safe Fetching\n\nThe library requires to manually define the entity class. Then the macro `FetchableManagedObject` can be used. \n\n```swift\n@FetchableManagedObject\nfinal class User: NSManagedObject {\n\n    @NSManaged var score = 0.0\n    @NSManaged var name: String? = \"\"\n}\n```\nThis makes `User` conform to `Fetchable` and ready to be used with the SafeFetching API.\n\nThen it's possible to use the DSL to build a request. The last step can either get the built request as `NSFetchRequest\u003cUser\u003e` or execute the request in the provided context.\n\n```swift\nUser.request()\n    .all(after: 10)\n    .where { $0.score \u003e= 15 || $0.name != \"Joe\" }\n    .sorted(by: .ascending(\\.score), .descending(\\.name))\n    .setting(\\.returnsDistinctResults, to: true)\n    .nsValue // returns NSFetchRequest\u003cUser\u003e\n```\n\n```swift\nUser.request()\n    .all(after: 10)\n    .where { $0.score \u003e= 15 || $0.name != \"Joe\" }\n    .sorted(by: .ascending(\\.score), .descending(\\.name))\n    .setting(\\.returnsDistinctResults, to: true)\n    .fetch(in: context) // returns [User]\n```\n\nAdvanced `NSPredicate` operators are also available like `BEGINSWITH` (`hasPrefix`).\n\n```swift\nUser.request()\n    .all()\n    .where { $0.name.hasPrefix(\"Do\", options: .caseInsensitive) }\n    .nsValue\n```\n\nMore about predicates in the [documentation](https://abridoux.github.io/SafeFetching/documentation/safefetching/build-predicates).\n\n### Convenience for NS types\nThe library also offers convenience functions to set a predicate of a `NSFetchRequest`.\n\n```swift\nrequest.predicate = .safe(on: User.self) { $0.score.isIn(10...20 }\n// or\nrequest.predicate = .safe(on: User.self) { (10...20).contains($0.score) }\n```\n\n## `NSPredicate`, `Predicate`\nWhy not using the `Predicate` macro? Two reasons.\n- It works only with SwiftData as of today (so iOS 17+, macOS 14+ ...). It doesn't work with CoreData.\n- It doesn't support everything that `NSPredicate` does when fetching a CoreData store.\n\nMeanwhile, `NSPredicate` requires to write everything in a `String`, which is very error-prone. \n\nWhereas this library tries to cover three objectives:\n1. Use compiler-checking to evaluate predicates and avoid runtime errors.\n2. Writing a request and especially a predicate should feel as natural as possible in Swift.\n3. No feature of NSPredicate to fetch a CoreData store should be left behind.\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FABridoux%2FSafeFetching","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FABridoux%2FSafeFetching","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FABridoux%2FSafeFetching/lists"}