I am trying to use a custom property inside a SwiftData model:
import SwiftData
struct Foo {
var name: String
}
@Model
final class Bar {
var id: String
var name: String
var foo: Foo
init(id: String, name: String) {
self.id = id
self.name = name
self.foo = Foo(name: name)
}
}
This is just a simplified example, in my real project Foo has many more variables and functions.
I get the following three "No exact matches in call to instance method setValue or getValue" errors:
{
@storageRestrictions(accesses: _$backingData, initializes: _foo)
init(initialValue) {
_$backingData.setValue(forKey: \.foo, to: initialValue)
_foo = _SwiftDataNoType()
}
get {
_$observationRegistrar.access(self, keyPath: \.foo)
return self.getValue(forKey: \.foo)
}
set {
_$observationRegistrar.withMutation(of: self, keyPath: \.foo) {
self.setValue(forKey: \.foo, to: newValue)
}
}
}
How can I solve this?
EDIT
Here is my updated code using a computed property, and this compiles:
@Model
final class Bar {
var id: String
var name: String
var foo: Foo {
return Foo(name: name)
}
init(id: String, name: String) {
self.id = id
self.name = name
}
}
However, if I try to change the name of foo:
func changeFoo(newName: String) {
foo.name = newName
}
I get another error:
Cannot assign to property: 'foo' is a get-only property
1 Answer 1
EDIT:
Although the answer below works, in the end I was able to make Foo from the external package conform to Codable.
Thanks to @Sweeper for pointing me to @Transient.
The following code works for both my example, and real project:
import SwiftData
struct Foo {
var name: String
}
@Model
final class Bar {
var id: String
var name: String
@Transient
var foo: Foo = .init(name: "")
init(id: String, name: String) {
self.id = id
self.name = name
}
func changeFoo(newName: String) {
foo.name = newName
}
}
1 Comment
foo a computed property with a get and set
Footype? Please read the documentation. How about makingFooconform toCodable? It really depends on what propertiesFoohas and what their types are.Foois from an external package, and does not conform toCodable. And it has many other properties from the package. I tried making it a computed property, which compiles, but then I cannot make changes to it, even though it is avar.set { self.name = newValue.name }. But why not just conform it toCodable? "From an external package" isn't really an excuse, unless you are anticipating that package will add its ownCodableconformance and therefore conflict with yours?self.nameandfoo.name? If there is only one source of truth (self.name), then you can just use@Transienton the other property to have SwiftData ignore it.