Releases: fatbobman/CoreDataEvolution
0.9.2
What's Changed
CoreDataEvolution 0.9.2 refines the MainActor Observation save-failure contract for saveObservedChanges.
saveObservedChangesnow clears only CoreDataEvolution's staged Observation metadata when a save fails.- The failing Core Data context is no longer rolled back by the library; rollback, reset, retry, or continued editing remain application-level policy.
- Registered producer cleanup now supports failure paths that know only the context, so CDE can discard staged producer metadata without touching user changes.
- The public Observation docs now present
saveObservedChangesas the actor-facing API for property-level Observation response, with clearer notes for direct saves and failure recovery.
Public API Highlights
No new public API surface is required for adopters. The existing Observation APIs remain the supported entry points:
@PersistentModel(observation: .mainActor)CDEObservationDomain(container:)CDEObservationDomain.saveObservedChanges(in:)NSModelActor.saveObservedChanges(in:)- generated
@NSModelActorinit(observationDomain:)andsaveObservedChanges()
Behavior Notes
On save failure, CDE now separates its own bookkeeping from business recovery:
- CDE clears staged Observation tokens and rethrows the save error.
- CDE does not call
rollback()on the actor or context. - Callers choose whether to rollback, reset, retry, or keep editing.
This keeps property-level Observation cleanup deterministic without discarding app-owned changes.
Validation
bash Scripts/run-tests.sh --filter ObservationRuntimeCorebash Scripts/run-tests.sh --filter ObservationIntegrationbash Scripts/run-tests.sh --filter MacroExpansionSnapshotTestsbash Scripts/run-tests.shbash Scripts/test-generated-flow.sh
0.9.1
What's Changed
0.9.1 is a focused patch release for the MainActor Observation rollout. It adds the Observation-aware generated @NSModelActor initializer and fixes the retained-domain teardown issue found during QA.
Highlights
-
@NSModelActornow generatesinit(observationDomain:)when initializer generation is enabled. -
The generated initializer derives the container from
CDEObservationDomain.modelContainer, creates a background context, registers it as an Observation producer, and retains the domain/registration for the actor's lifetime. -
Generated actors also receive a no-argument
saveObservedChanges().- Actors created with
init(observationDomain:)use the retained registered-context save path. - Actors created with
init(container:)fall back tomodelContext.save()and emit a one-time warning that no CDE Observation metadata will be produced.
- Actors created with
-
Inline construction is supported:
let writer = ItemWriter(observationDomain: CDEObservationDomain(container: container))
Fixes
- Fixed off-main teardown of a retained
CDEObservationDomainby usingisolated deinit. - Generated observed actors now invalidate their retained producer registration in
deinit, and the domain removes invalidated registrations from its retained list. - Simplified the generated
saveObservedChanges()path to remove the dead branch reported by QA.
Compatibility Notes
- MainActor Observation is now gated with
#if compiler(>=6.2). - The package tools-version and non-Observation features remain Swift 6.0-compatible.
- Observation-specific APIs require a Swift 6.2+ compiler and the existing iOS 17 / macOS 14 platform families.
NSModelActor.saveObservedChanges(in:)remains available for custom or plain actor contexts that do not retain a producer registration.
Documentation
- Updated
Docs/NSModelActorGuide.md,Docs/ObservationGuide.md, and the DocC overview for the generated initializer, inline domain lifetime, fallback warning, custom initializer cleanup, and Swift compiler 6.2+ Observation requirement.
Validation
bash Scripts/run-tests.shpassed with 340 tests / 44 suites.bash Scripts/test-generated-flow.shpassed, including external generated fixture build and run.git diff --checkpassed.
0.9.0
What's Changed
CoreDataEvolution 0.9.0 adds opt-in MainActor Swift Observation for generated Core Data models.
- Add
@PersistentModel(observation: .mainActor)for iOS 17+ / macOS 14+ platform families. - Add
CDEObservationDomain, a retained container-bound runtime that activates observation routing forcontainer.viewContext. - Let SwiftUI and
withObservationTrackingread CoreDataEvolution-generated Core Data accessors directly, including relationship chains, without forcing extraObservableObjectprojection layers into view structure. - Route saved changes with property-level precision when the producer can provide changed Core Data keys.
- Support precise routes for plain
viewContext.save(),NSModelActor.saveObservedChanges(in:),NSMainModelActor.saveObservedChanges(in:), registered ordinary background contexts, and wrapper-owned context saves. - Add lifecycle and fallback handling for rollback, refresh, reset, delete, temporary object ID rekeying, batch operations, unregistered contexts, and objectID-only merges.
- Preserve precise local/background routes across store re-merges with
CDEPreciseRouteEchoSuppression, including the commonNSPersistentCloudKitContainer/ Persistent History Tracking echo. - Add
CDE_OBSERVATION_DEBUGandCDEObservationDomain.isDebugLoggingEnabledfor opt-in unified logging diagnostics. - Add the public
Docs/ObservationGuide.md, update README and DocC, and keep internal mechanism / implementation documents underDocs/Development.
Public API Highlights
PersistentModelObservationMode.mainActorCDEObservationDomain(container:preciseRouteEchoSuppression:)CDEObservationDomain.registerChangeProducer(context:)CDEObservationDomain.newObservedBackgroundContext()CDEObservationDomain.saveObservedChanges(in:)CDEObservationDomain.rollbackObservedChanges()CDEPreciseRouteEchoSuppressionNSModelActor.saveObservedChanges(in:)NSMainModelActor.saveObservedChanges(in:)
Behavior Notes
- Observation is opt-in. Plain
@PersistentModeland explicitobservation: .nonekeep the non-observable generated output. - Only CoreDataEvolution-generated accessors participate in observation. Raw
@NSManagedproperties and custom getters that bypass generated accessors are not observable. - Refresh is save-gated: generated setters write Core Data values, while SwiftUI refresh happens after save, merge, or lifecycle fallback.
- Unregistered contexts, batch operations, and external CloudKit imports fall back to objectID / all-observable-key-path invalidation when changed-key metadata is unavailable.
- Field-level precision is useful, but the main goal is cognitive clarity: SwiftUI can stay close to the persisted Core Data object graph, especially in relationship-heavy screens.
Validation
bash Scripts/run-tests.shpassed withcom.apple.CoreData.ConcurrencyDebug=1enabled: 334 tests / 44 suites.bash Scripts/test-generated-flow.shpassed: generated source unchanged, conformance and exact validation both reported 0 errors / 0 warnings, and the external generated-flow fixture built and ran successfully.
0.8.12
What's Changed
- Fix nested to-one typed path predicates such as
Memo.path.itemData.item.note.id.equals(noteID). - Preserve composed persistent key paths across multi-hop to-one relationship chains.
- Carry leaf storage metadata into predicate helpers so
.rawvalues still use the RawRepresentable overload correctly. - Document multi-hop to-one predicate support in the Typed Path guide.
Validation: bash Scripts/run-tests.sh --filter TypedPath passed with 25 tests.
0.8.11
0.8.10
CoreDataEvolution 0.8.10
This release adds generated to-many relationship count accessors and completes the related tooling/config plumbing.
Added
@PersistentModel(generateToManyCount: Bool = true)- Generated
relationshipNameCountaccessors for to-many relationships - CLI/config support for
generateToManyCount/--generate-to-many-count
Fixed
- Preserve
generateToManyCountthrough tooling IR generation - Forward
generateToManyCountforinspect --config - Add regression coverage for generation policy and inspect config propagation
Verification
bash Scripts/run-tests.sh
0.8.9
Full Changelog: 0.8.8...0.8.9
0.8.8
Full Changelog: 0.8.7...0.8.8
0.8.7
Full Changelog: 0.8.6...0.8.7
0.8.6
Highlights
- Allow required default-storage attributes without explicit defaults.
- Normalize underscored runtime default literals in runtime schema building.
- Add field-level validate optionality ignores via ignoreOptionality: true.
- Skip formatting cde-tool managed generated files in the pre-commit hook to avoid exact-validation drift.