I'm creating an app using SwiftData with two models: Item and Detail, where an Item stores an array of Detail objects.
A Detail can represent different kinds of mutually exclusive data, for example:
- text
- date
- location
- etc
Each type also has different SwiftUI views for creating, editing, and displaying the value.
I'm new to Swift and SwiftUI, so I'm not sure what the pragmatic approach is for implementing these different types.
My first idea was defining a protocol with an associatedtype and separate model implementations per value type:
protocol Detail {
associatedtype ValueType
var name: String { get set }
var value: ValueType { get set }
var forDisplay: String { get }
}
@Model
final class TextDetail: Detail {
var name: String
var value: String
var forDisplay: String {
value
}
init(name: String, value: String) {
self.name = name
self.value = value
}
}
@Model
final class DateDetail: Detail {
var name: String
var value: Date
var forDisplay: String {
value.formatted()
}
init(name: String, value: Date) {
self.name = name
self.value = value
}
}
However, this doesn't enforce exhaustiveness, and it feels rather verbose when the implementations don't differ that much.
The other approach I thought of was using an enum with associated values as the data type:
enum DetailValue {
case text(String)
case date(Date)
var forDisplay: String {
switch self {
case .text(let text):
text
case .date(let date):
date.formatted()
}
}
}
@Model
final class Detail {
var name: String
var value: DetailValue
init(name: String, value: DetailValue) {
self.name = name
self.value = value
}
}
Though, I'm unsure whether SwiftData handles this well.
I'd highly appreciate suggestions, thanks :)