When adding a keyboardShortcut to a Button that references the @StateObject model in Button.action as shown below, model.deinit is not called even if this view has disappeared. On redisplaying, both model.deinit and model.init are called.
Without the keyboardShortcut, model.deinit is called when the screen has disappeared. Also, when I explicitly specified [weak model = self.model], the deinit was called.
Is it a bug that we need to use weak when using keyboardShortcut?
Test environment
- Xcode Version 15.0 (15A240d)
- iOS 17.0 Simulator iOS 16.4 Simulator, (iPhone SE 3rd generation)
import SwiftUI
@main
struct StateObjectDeinitSampleApp: App {
var body: some Scene {
WindowGroup {
NavigationStack {
MainView()
}
}
}
}
struct MainView: View {
var body: some View {
NavigationLink(value: true) {
Text("GO")
}
.navigationDestination(for: Bool.self) { value in
if value {
ContentView()
}
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
VStack {
Button("Toggle") {
model.flag.toggle()
}
.keyboardShortcut(.space, modifiers: [])
}
.padding()
}
}
@MainActor
class Model: ObservableObject{
@Published var flag: Bool = false
init() {
print("Model.init")
}
deinit {
print("Model.deinit")
}
}
// weak.
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
VStack {
Button("Toggle") { [weak model = self.model] in
model?.flag.toggle()
}
.keyboardShortcut(.space, modifiers: [])
}
.padding()
}
}