簡體   English   中英

當 SwiftUI 視圖被關閉時,如何發送最后一條消息並關閉套接字?

[英]How to send a last message and close the socket when a SwiftUI view is dismissed?

我有一個帶有ObservedObjectSwiftUI 工作表視圖,用於處理 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM