I have a SwiftUI sheet view with an ObservedObject that handles tcp communication, when this sheet gets dismissed I need it to send a last tcp message and then close the socket. The onDisappear event never seems to get triggered (Edit: found out the culprit its because I'm presenting the sheet using a UIHostingController, still need a solution) I've tried putting it I the form, navigation view, tried creating a new stack for it, nothing worked. So I've tried using my ObservedObject deinit but this gives me a bad access error if I try to reopen the view fast after closing it.
deinit {
let msg = getUpdatedTimersString()
self.connection.sendMsg(msg, success: connection.close)
}
from my connection class that uses Network Framework
func sendMsg(_ message: String, success: @escaping () -> Void = { }, error: @escaping () -> Void = { }) {
let msg = message + "\r\n"
let data: Data? = msg.data(using: .utf8)
debugPrint("Sending: \(msg)")
connection.send(content: data, completion: .contentProcessed { (sendError) in
if let sendError = sendError {
self.debug("\(sendError)")
error()
} else {
success()
}
})
}
func close() {
connection.cancel()
}
Edit: adding the view code below
struct ScheduleView: View {
@ObservedObject var scheduleManager = ScheduleManager() // This handles the tcp communication, the deinit you see above is from this
var body: some View {
NavigationView {
Form {
ForEach(scheduleManager.timers) { timer in
ScheduleForm(scheduleManager: self.scheduleManager, timer: timer).onDisappear { debugPrint("schedule form row disappeared") } // This is just a view that adds a section header and a DatePicker to the form for each timer
}
}.onDisappear { debugPrint("form disappeared") }
.navigationBarTitle(Text("Schedule"), displayMode: .inline)
}.onDisappear() { debugPrint("nav disappeared") }
}
}
None of these onDisappear work for me, the one in the ScheduleForm rows is the only one that even triggers for me, but it triggers when the sheet is created and every time I scroll a row out of sight, but not when I dismiss the sheet.
Solution:
final class ScheduleController: UIHostingController<ScheduleView> {
required init?(coder: NSCoder) {
super.init(coder: coder, rootView: ScheduleView())
}
init() {
super.init(rootView: ScheduleView())
}
override func viewWillDisappear(_ animated: Bool) {
rootView.scheduleManager.updateTimers() // this sends the last message
}
override func viewDidDisappear(_ animated: Bool) {
rootView.scheduleManager.connection.close // this closes the connection
}
}