First off, given that I didn't find a tag for Code Review, I hope I am not out of scope for the forums here.
Second, some background. I am a long time Windows Power Shell developer, moving to Swift because I don't like self loathing. :)
Currently I am trying to get my head around SwiftData, and experimenting with creating a Service to handle the actual SwiftData functionality, and a Manager to handle various tasks that relate to instances of the Model. I am doing this realizing that it MAY NOT be the best approach, but it gives me reps both producing code and thinking about how to solve a problem, which I think is useful even if the actual product in throw away. That said, I am hoping someone with more experience than I can comment on this approach, especially with respect to expanding to more models, more complex models, lots of data and a desire to use ModelActor
eventually.
DataManagerApp.swift
import SwiftData
import SwiftUI
@main
struct DataManagerApp: App {
let container: ModelContainer
init() {
let schema = Schema([DataModel.self])
let config = ModelConfiguration("SwiftDataStore", schema: schema)
do {
let modelContainer = try ModelContainer(for: schema, configurations: config)
DataService.instance.assignContainer(modelContainer)
container = modelContainer
} catch {
fatalError("Could not configure SwiftData ModelContainer.")
}
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(container)
}
}
}
DataModel.swift
import Foundation
import SwiftData
@Model
final class DataModel {
var date: Date
init(date: Date) {
self.date = date
}
}
final class DataService {
static let instance = DataService()
private var modelContainer: ModelContainer?
private var modelContext: ModelContext?
private init() {}
func assignContainer(_ container: ModelContainer) {
if modelContainer == nil {
modelContainer = container
modelContext = ModelContext(modelContainer!)
} else {
print("Attempted to assign ModelContainer more than once.")
}
}
func addModel(_ dataModel: DataModel) {
modelContext?.insert(dataModel)
}
func removeModel(_ dataModel: DataModel) {
modelContext?.delete(dataModel)
}
}
final class ModelManager {
static let instance = ModelManager()
let dataService: DataService = DataService.instance
private init() {}
func newModel() {
let newModel = DataModel(date: Date.now)
DataService.instance.addModel(newModel)
}
}
ContentView.swift
import SwiftData
import SwiftUI
struct ContentView: View {
@Environment(\.modelContext) var modelContext
@State private var sortOrder = SortDescriptor(\DataModel.date)
@Query(sort: [SortDescriptor(\DataModel.date)]) var models: [DataModel]
var body: some View {
VStack {
addButton
List {
ForEach(models) { model in
modelRow(model)
}
}
.listStyle(.plain)
}
.padding()
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
addButton
}
}
}
}
private extension ContentView {
var addButton: some View {
Button("+ Add") {
ModelManager.instance.newModel()
}
}
func modelRow(_ model: DataModel) -> some View {
HStack {
Text(model.date.formatted(date: .numeric, time: .shortened))
Spacer()
}
}
}