[英]SwiftUI NavigationView adding extra view onto stack when sheet is dismissed
[英]How to send a last message and close the socket when a SwiftUI view is dismissed?
我有一个带有ObservedObject的SwiftUI 工作表视图,用于处理 tcp 通信,当该工作表被解除时,我需要它发送最后一条 tcp 消息,然后关闭套接字。 onDisappear事件似乎从未被触发(编辑:找出了罪魁祸首,因为我正在使用UIHostingController呈现工作表,仍然需要一个解决方案)我试过把它放在表单、导航视图中,尝试创建一个新堆栈为此,没有任何效果。 所以我尝试使用我的ObservedObject deinit 但是如果我在关闭视图后尝试快速重新打开视图,这会给我一个错误的访问错误。
deinit {
let msg = getUpdatedTimersString()
self.connection.sendMsg(msg, success: connection.close)
}
来自我使用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()
}
编辑:添加下面的视图代码
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") }
}
}
这些onDisappear 都不适合我, ScheduleForm行中的行是唯一一个甚至为我触发的行,但它在创建工作表时以及每次我滚动一行看不见时触发,但在我关闭工作表时不会触发.
解决方案:
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
}
}
我做的第一件事是更改您的函数签名以使用单个闭包来实现成功和错误完成。
func sendMsg(_ message: String, completion: ((Bool) ->())? = nil)
然后我们可以在 onDisappear 修饰符中使用它。 完成后关闭连接。
struct ContentView: View {
var body: some View {
Text("Hello World").onDisappear {
sendMsg("last msg", completion: { completed in
close()
})
}
}
}
我经常做的是这样的:
struct ScheduleView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@ObservedObject var scheduleManager = ScheduleManager()
var body: some View {
NavigationView {
Form {
ForEach(scheduleManager.timers) { timer in
ScheduleForm(scheduleManager: self.scheduleManager, timer: timer)
}
}
}.onDisappear(perform: doExit)
.navigationBarTitle(Text("Schedule"), displayMode: .inline)
}
func doExit() {
// do your closing etc ... here
// then to go back to the previous view
self.presentationMode.wrappedValue.dismiss()
}
}
我有这个非常粗略的测试工作。 显示一个工作表,当您滑动时,将触发 onDisappear 并执行 doExit 功能。 对 UIHostingController 一无所知。
struct ContentView: View {
@State var testArray = ["one", "two", "three"]
@State var showMe = false
var body: some View {
Button(action: { self.showMe = true}) {
Text("Press button")
}.sheet(isPresented: $showMe, onDismiss: {self.showMe = false}) { TestView(scheduleManager: self.testArray) }
}
}
struct TestView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var scheduleManager: [String]
var body: some View {
NavigationView {
Form {
ForEach(scheduleManager, id: \.self) { timer in
Text(timer)
}
}
}.onDisappear(perform: doExit)
}
func doExit() {
print("-----> TestView doExit")
// then to go back to the previous view
self.presentationMode.wrappedValue.dismiss()
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.