Reputation: 1467
In Core Data I can implement a custom NSManagedObject property getter/setter:
@objc var name: String {
get {
willAccessValue(forKey: #keyPath(name))
defer { didAccessValue(forKey: #keyPath(name)) }
let name = primitiveValue(forKey: #keyPath(name)) as? String
return name ?? ""
}
set {
willChangeValue(forKey: #keyPath(name))
defer { didChangeValue(forKey: #keyPath(name)) }
// Trimming is just an example, it could be any data cleanup.
let name = newValue.trimmingCharacters(in: .whitespacesAndNewlines)
setPrimitiveValue(name, forKey: #keyPath(name))
}
}
How to achieve that in a SwiftData @Model
? I don't want to create a second property based on a persisted one but have only a single property.
Why not 2 properties:
_name
or choose a new, second-rate computed property name like nameNew
.#Predicate
.Upvotes: 1
Views: 612
Reputation: 1467
There doesn't seem to be an easy solution using a single property. But it's possible to address the pain points.
@Attribute(originalName: "name")
private(set) var _name = ""
var name: String {
get { _name }
set { _name = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
}
@Attribute(originalName: "name")
is only needed if you change the stored property name from name
to _name
and have data to migrate. If you forget this, the data will be deleted. ⚠️_name
is private(set)
to ensure clean data via the name
setter. It cannot be fully private because as a computed property name
is not available in #Predicate
.private(set) var name = ""
var name2: String {
get { name }
set { name = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
}
name2
stands for two-way (get and set).name2
instead of name
where possible, which is not as intuitive as using name
over _name
. ⚠️Upvotes: 1