How to listen, cancel, and re-listen with NWListener?

I have the following NWListener. I am to listen only while the app is in the foreground, and re-listen when it come back from background. However I call my stop() function and if I call start() subsequently it fils. Also if the app is terminated (in debugger or task manager) I cannot launch the app again for ~5 seconds because the listen() will fail.

 { 
    self.port = NWEndpoint.Port(rawValue: port)!
	listenerState = .cancelled
	self.eventHandler = handler
	let parameters = NWParameters(tls: nil)
	parameters.allowLocalEndpointReuse = true
	parameters.includePeerToPeer = true
	let wsOptions = NWProtocolWebSocket.Options()
	wsOptions.autoReplyPing = true
	parameters.defaultProtocolStack.applicationProtocols.insert(wsOptions, at: 0)
	do {
	  listener = try NWListener(using: parameters, on: self.port)
	  listener!.stateUpdateHandler = self.stateDidChange(to:)
	  listener!.newConnectionHandler = self.didAccept(nwConnection:)
	} catch {
		print(#function, error)
	}
deinit {
	stop()
}
func start() throws {
    print("Server starting...")
	listener!.stateUpdateHandler = self.stateDidChange(to:)
	listener!.newConnectionHandler = self.didAccept(nwConnection:)
	listener!.start(queue: .main)
	print("Server started.")
	eventHandler()
  }
 func stop() {
      self.listener!.stateUpdateHandler = nil
      self.listener!.newConnectionHandler = nil
      self.listener!.cancel()
	  print("Server cancelled")
      connection?.stop()
      connection?.didStopCallback = nil
	  connection = nil
	  eventHandler()
}

When it fails, it logs a backgrace (logs below) however there is no way for me to know it has failed. there is no NWListner.state variable, but there is a stateDidChange() handler which can only be called by the framework when the state change occurs however having been backgrounded, the last reported state is not valid.

There's a couple issues here

  1. I cannot quickly cancel() and listen() on the same port (this seems to be unique to swift as a native implementation works fine)
  2. There is no state variable to check.
  3. I get a stacktrace dumped to the console rather than some catchable error. So My app has no way to know that the listen() failed.

Server starting...
2020-08-12 16:29:42.476799-0400 rfa-ios-native[821:464825] nw listener set queue Error in client: nw listener set queue called after nw listener start
2020-08-12 16:29:42.480218-0400 rfa-ios-native[821:464825] nw listener set queue Error in client: nw listener set queue called after nw listener start, dumping backtrace:
[arm64] libnetcore-1880.100.30
0 libnetwork.dylib 0x000000019218b060 _ nw create backtrace string + 120
1 libnetwork.dylib 0x00000001920a68bc nw listener set queue + 228
2 libswiftNetwork.dylib 0x00000001c6556e74 $s7Network10NWListenerC5start5queueySo012OS
dispatch D0C tF + 56
...
Server started.
2020-08-12 16:29:42.482909-0400 rfa-ios-native[821:464835] nw listener start block invoke [L1] In wrong state for start
2020-08-12 16:29:42.483533-0400 rfa-ios-native[821:464835] nw listener start block invoke [L1] In wrong state for start, dumping backtrace:
[arm64] libnetcore-1880.100.30
0 libnetwork.dylib 0x000000019218b060 _ nw create backtrace string + 120
1 libnetwork.dylib 0x00000001920a89e8 6B86071A-0DFC-3EFD-A798-615EC6A7D591 + 3578344
2 libdispatch.dylib 0x000000010068dd10 dispatch call block and_release + 32
...

Terms of Service

Privacy Policy

Cookie Policy