Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d08c312c62 |
@@ -541,7 +541,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = PortfolioJournal/PortfolioJournalDebug.entitlements;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_ASSET_PATHS = PortfolioJournal/Assets.xcassets;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -582,7 +582,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "porfoliojournal";
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_ASSET_PATHS = PortfolioJournal/Assets.xcassets;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -739,7 +739,7 @@
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_ENTITLEMENTS = PortfolioJournalWidgetExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_ASSET_PATHS = PortfolioJournalWidget/Assets.xcassets;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = NO;
|
||||
@@ -774,7 +774,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "Portfolio Journalwidget";
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_ASSET_PATHS = PortfolioJournalWidget/Assets.xcassets;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = NO;
|
||||
@@ -805,7 +805,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||
@@ -829,7 +829,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||
@@ -852,7 +852,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||
@@ -875,7 +875,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||
@@ -899,7 +899,7 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = PortfolioJournalQuickUpdateExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
GENERATE_INFOPLIST_FILE = NO;
|
||||
INFOPLIST_FILE = PortfolioJournalQuickUpdate/Info.plist;
|
||||
@@ -927,7 +927,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = PortfolioJournalQuickUpdateExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 50;
|
||||
CURRENT_PROJECT_VERSION = 56;
|
||||
DEVELOPMENT_TEAM = 2825Q76T7H;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "PortfolioJournal QuickUpdate AppStore";
|
||||
GENERATE_INFOPLIST_FILE = NO;
|
||||
|
||||
@@ -7,8 +7,14 @@ public class Account: NSManagedObject, Identifiable {
|
||||
return NSFetchRequest<Account>(entityName: "Account")
|
||||
}
|
||||
|
||||
@NSManaged public var id: UUID
|
||||
@NSManaged public var name: String
|
||||
@objc public var id: UUID {
|
||||
get { safeValue(forKey: "id", fallback: UUID(), healing: true) }
|
||||
set { setManagedValue(newValue, forKey: "id") }
|
||||
}
|
||||
@objc public var name: String {
|
||||
get { safeValue(forKey: "name", fallback: "") }
|
||||
set { setManagedValue(newValue, forKey: "name") }
|
||||
}
|
||||
@NSManaged public var createdAt: Date
|
||||
@NSManaged public var currency: String?
|
||||
@NSManaged public var inputMode: String
|
||||
|
||||
@@ -8,10 +8,22 @@ public class Category: NSManagedObject, Identifiable {
|
||||
return NSFetchRequest<Category>(entityName: "Category")
|
||||
}
|
||||
|
||||
@NSManaged public var id: UUID
|
||||
@NSManaged public var name: String
|
||||
@NSManaged public var colorHex: String
|
||||
@NSManaged public var icon: String
|
||||
@objc public var id: UUID {
|
||||
get { safeValue(forKey: "id", fallback: UUID(), healing: true) }
|
||||
set { setManagedValue(newValue, forKey: "id") }
|
||||
}
|
||||
@objc public var name: String {
|
||||
get { safeValue(forKey: "name", fallback: "") }
|
||||
set { setManagedValue(newValue, forKey: "name") }
|
||||
}
|
||||
@objc public var colorHex: String {
|
||||
get { safeValue(forKey: "colorHex", fallback: "#6B7280") }
|
||||
set { setManagedValue(newValue, forKey: "colorHex") }
|
||||
}
|
||||
@objc public var icon: String {
|
||||
get { safeValue(forKey: "icon", fallback: "questionmark") }
|
||||
set { setManagedValue(newValue, forKey: "icon") }
|
||||
}
|
||||
@NSManaged public var sortOrder: Int16
|
||||
@NSManaged public var createdAt: Date
|
||||
@NSManaged public var allocationTarget: NSNumber?
|
||||
|
||||
@@ -7,8 +7,14 @@ public class Goal: NSManagedObject, Identifiable {
|
||||
return NSFetchRequest<Goal>(entityName: "Goal")
|
||||
}
|
||||
|
||||
@NSManaged public var id: UUID
|
||||
@NSManaged public var name: String
|
||||
@objc public var id: UUID {
|
||||
get { safeValue(forKey: "id", fallback: UUID(), healing: true) }
|
||||
set { setManagedValue(newValue, forKey: "id") }
|
||||
}
|
||||
@objc public var name: String {
|
||||
get { safeValue(forKey: "name", fallback: "") }
|
||||
set { setManagedValue(newValue, forKey: "name") }
|
||||
}
|
||||
@NSManaged public var targetAmount: NSDecimalNumber?
|
||||
@NSManaged public var targetDate: Date?
|
||||
@NSManaged public var isActive: Bool
|
||||
|
||||
@@ -7,8 +7,14 @@ public class InvestmentSource: NSManagedObject, Identifiable {
|
||||
return NSFetchRequest<InvestmentSource>(entityName: "InvestmentSource")
|
||||
}
|
||||
|
||||
@NSManaged public var id: UUID
|
||||
@NSManaged public var name: String
|
||||
@objc public var id: UUID {
|
||||
get { safeValue(forKey: "id", fallback: UUID(), healing: true) }
|
||||
set { setManagedValue(newValue, forKey: "id") }
|
||||
}
|
||||
@objc public var name: String {
|
||||
get { safeValue(forKey: "name", fallback: "") }
|
||||
set { setManagedValue(newValue, forKey: "name") }
|
||||
}
|
||||
@NSManaged public var notificationFrequency: String
|
||||
@NSManaged public var customFrequencyMonths: Int16
|
||||
@NSManaged public var isActive: Bool
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import CoreData
|
||||
|
||||
// MARK: - Nil-tolerant accessors for CloudKit-synced attributes
|
||||
//
|
||||
// Attributes declared non-optional in Swift (`id: UUID`, `date: Date`, …) CAN
|
||||
// be nil at runtime: NSPersistentCloudKitContainer merges records from other
|
||||
// devices in stages, and deleted objects may still be referenced by live views.
|
||||
// Reading them through `@NSManaged` force-bridges nil and crashes
|
||||
// (`UUID/Date._unconditionallyBridgeFromObjectiveC`) — seen in production in
|
||||
// SwiftUI ForEach identity (nil id) and ChartsViewModel.monthlyTotals (nil
|
||||
// date). These helpers read the primitive value and fall back safely.
|
||||
extension NSManagedObject {
|
||||
/// Reads a primitive attribute, returning `fallback` when nil. With
|
||||
/// `healing: true` the fallback is also written back to the primitive
|
||||
/// (without dirtying the object) so identity stays stable for the session.
|
||||
func safeValue<T>(forKey key: String, fallback: @autoclosure () -> T, healing: Bool = false) -> T {
|
||||
willAccessValue(forKey: key)
|
||||
defer { didAccessValue(forKey: key) }
|
||||
if let value = primitiveValue(forKey: key) as? T {
|
||||
return value
|
||||
}
|
||||
let healed = fallback()
|
||||
if healing {
|
||||
setPrimitiveValue(healed, forKey: key)
|
||||
}
|
||||
return healed
|
||||
}
|
||||
|
||||
func setManagedValue<T>(_ value: T, forKey key: String) {
|
||||
willChangeValue(forKey: key)
|
||||
setPrimitiveValue(value, forKey: key)
|
||||
didChangeValue(forKey: key)
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,21 @@ public class Snapshot: NSManagedObject, Identifiable {
|
||||
return NSFetchRequest<Snapshot>(entityName: "Snapshot")
|
||||
}
|
||||
|
||||
@NSManaged public var id: UUID
|
||||
@NSManaged public var date: Date
|
||||
@objc public var id: UUID {
|
||||
get { safeValue(forKey: "id", fallback: UUID(), healing: true) }
|
||||
set { setManagedValue(newValue, forKey: "id") }
|
||||
}
|
||||
@objc public var date: Date {
|
||||
get { safeValue(forKey: "date", fallback: .distantPast) }
|
||||
set { setManagedValue(newValue, forKey: "date") }
|
||||
}
|
||||
@NSManaged public var value: NSDecimalNumber?
|
||||
@NSManaged public var contribution: NSDecimalNumber?
|
||||
@NSManaged public var notes: String?
|
||||
@NSManaged public var createdAt: Date
|
||||
@objc public var createdAt: Date {
|
||||
get { safeValue(forKey: "createdAt", fallback: .distantPast) }
|
||||
set { setManagedValue(newValue, forKey: "createdAt") }
|
||||
}
|
||||
@NSManaged public var source: InvestmentSource?
|
||||
|
||||
public override func awakeFromInsert() {
|
||||
|
||||
Reference in New Issue
Block a user