Skip to content

Commit 23e83f2

Browse files
committed
Added Typed NSManagedObjectIDs
1 parent 31c05af commit 23e83f2

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Helpful tools for Core Data
1919
- [PersistentHistoryTracker actor](#persistenthistorytracker-actor)
2020
- [SwiftUI Integration](#swiftui-integration)
2121
- [CRUD Helpers](#crud-helpers)
22+
- [Typed NSManagedObjectID](#typed-nsmanagedobjectid)
2223
- [Updatable Protocol](#updatable-protocol)
2324
- [Persistable Protocol](#persistable-protocol)
2425
- [NSManagedObjectContext Helpers](#nsmanagedobjectcontext-helpers)
@@ -262,6 +263,19 @@ You must set the DataStack into a view's environment using the `dataStackEnviron
262263

263264
# CRUD Helpers
264265

266+
### Typed NSManagedObjectID
267+
268+
Use `TypedObjectID` in place of `NSManagedObjectID` anywhere that you want to enforce type safety around the ID. Because both `NSManagedObjectID` and the `TypedObjectID` wrapper are `Sendable`, they are the best way to send references to `NSManagedObject` between contexts.
269+
```swift
270+
let viewContextPerson = Person(...) // get a person on the ViewContext
271+
let personId = TypedObjectID(viewContextPerson.objectID) // personId refers only to Person type
272+
273+
try backgroundContext.perform {
274+
// get a reference to the same Person from storage, but safe for this context:
275+
let backgroundContextPerson = try backgroundContext.existingObject(with: personId)
276+
}
277+
```
278+
265279
### Updatable Protocol
266280

267281
Add the `Updatable` protocol to your Model types to get some free functions. Protocol conformance has no requirements except that the implementing type is a `NSManagedObject` subclass.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// TypedObjectID.swift
3+
// RCDataKit
4+
//
5+
// Created by Ryan Linn on 11/24/24.
6+
//
7+
8+
import CoreData
9+
10+
/// A wrapper around `NSManagedObjectID` that includes the `NSManagedObject` class type for Swift
11+
/// type safety.
12+
public struct TypedObjectID<T: NSManagedObject>: Sendable, Hashable {
13+
public let wrapped: NSManagedObjectID
14+
15+
public init(_ object: T) {
16+
wrapped = object.objectID
17+
}
18+
}
19+
20+
extension NSManagedObjectContext {
21+
/// Gets an existing object from the context using a `TypedObjectID`.
22+
public func existingObject<T: NSManagedObject>(with typedId: TypedObjectID<T>) throws -> T {
23+
try existing(T.self, withID: typedId.wrapped)
24+
}
25+
}

0 commit comments

Comments
 (0)