Fix sync iCloud del Goal: accessor nil-tolerante en createdAt (Goal/Account/InvestmentSource)

El modelo declara createdAt optional=YES pero las clases lo tenían @NSManaged var createdAt: Date
(no-opcional). Al materializar un registro importado por CloudKit con createdAt transitoriamente
nil, el acceso revienta el merge → contribuye al CKErrorPartialFailure y a que el Goal no sincronice.
Mismo patrón safeValue/setManagedValue ya aplicado a Snapshot (hotfix b76b8f8) que no cubrió estas 3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZFmGhbWzibhApev3C4554
This commit is contained in:
alexandrev-tibco
2026-07-21 15:22:42 +02:00
parent 137931b37c
commit 7eb7cb81d4
3 changed files with 21 additions and 3 deletions
@@ -15,7 +15,13 @@ public class Account: NSManagedObject, Identifiable {
get { safeValue(forKey: "name", fallback: "") } get { safeValue(forKey: "name", fallback: "") }
set { setManagedValue(newValue, forKey: "name") } set { setManagedValue(newValue, forKey: "name") }
} }
@NSManaged public var createdAt: Date // createdAt is optional in the model; a non-optional @NSManaged Date crashes the
// CloudKit merge when an imported record materialises with a transient nil.
// Same nil-tolerant accessor pattern already applied to Snapshot.
@objc public var createdAt: Date {
get { safeValue(forKey: "createdAt", fallback: .distantPast) }
set { setManagedValue(newValue, forKey: "createdAt") }
}
@NSManaged public var currency: String? @NSManaged public var currency: String?
@NSManaged public var inputMode: String @NSManaged public var inputMode: String
@NSManaged public var notificationFrequency: String @NSManaged public var notificationFrequency: String
@@ -18,7 +18,13 @@ public class Goal: NSManagedObject, Identifiable {
@NSManaged public var targetAmount: NSDecimalNumber? @NSManaged public var targetAmount: NSDecimalNumber?
@NSManaged public var targetDate: Date? @NSManaged public var targetDate: Date?
@NSManaged public var isActive: Bool @NSManaged public var isActive: Bool
@NSManaged public var createdAt: Date // createdAt is optional in the model; a non-optional @NSManaged Date crashes the
// CloudKit merge when an imported record materialises with a transient nil.
// Same nil-tolerant accessor pattern already applied to Snapshot.
@objc public var createdAt: Date {
get { safeValue(forKey: "createdAt", fallback: .distantPast) }
set { setManagedValue(newValue, forKey: "createdAt") }
}
@NSManaged public var account: Account? @NSManaged public var account: Account?
public override func awakeFromInsert() { public override func awakeFromInsert() {
@@ -19,7 +19,13 @@ public class InvestmentSource: NSManagedObject, Identifiable {
@NSManaged public var customFrequencyMonths: Int16 @NSManaged public var customFrequencyMonths: Int16
@NSManaged public var isActive: Bool @NSManaged public var isActive: Bool
@NSManaged public var monthlyContribution: NSDecimalNumber? @NSManaged public var monthlyContribution: NSDecimalNumber?
@NSManaged public var createdAt: Date // createdAt is optional in the model; a non-optional @NSManaged Date crashes the
// CloudKit merge when an imported record materialises with a transient nil.
// Same nil-tolerant accessor pattern already applied to Snapshot.
@objc public var createdAt: Date {
get { safeValue(forKey: "createdAt", fallback: .distantPast) }
set { setManagedValue(newValue, forKey: "createdAt") }
}
@NSManaged public var category: Category? @NSManaged public var category: Category?
@NSManaged public var account: Account? @NSManaged public var account: Account?
@NSManaged public var snapshots: NSSet? @NSManaged public var snapshots: NSSet?