Skip to content

Commit 7bee5a7

Browse files
committed
Added handling for iOS hibernation
1 parent 1662b0e commit 7bee5a7

File tree

2 files changed

+71
-10
lines changed

2 files changed

+71
-10
lines changed

todoapp/Bridge.swift

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import SwiftUI
1212

1313
class Bridge {
1414
var webview: WebViewController?
15-
let listener: NWListener
15+
var listener: NWListener?
1616
let home: URL
1717
var lastURL: URL?
18+
static public var instance: Bridge?
19+
var erlangStarted = false
1820

1921
func setWebView(view :WebViewController) {
2022
self.webview = view
@@ -38,10 +40,8 @@ class Bridge {
3840
private var connectionsByID: [Int: ServerConnection] = [:]
3941

4042
init() throws {
43+
print("bridge init()")
4144
home = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0].appendingPathComponent(Bundle.main.bundleIdentifier!)
42-
listener = try! NWListener(using: .tcp, on: NWEndpoint.Port.any)
43-
listener.stateUpdateHandler = self.stateDidChange(to:)
44-
listener.newConnectionHandler = self.didAccept(nwConnection:)
4545

4646
// Extracting the app
4747
let infoAttr = try FileManager.default.attributesOfItem(atPath: zipFile().path)
@@ -87,7 +87,30 @@ class Bridge {
8787
//}
8888

8989
print("Server starting...")
90-
listener.start(queue: .global())
90+
// setupListener()
91+
Bridge.instance = self
92+
}
93+
94+
func setupListener() {
95+
let l = try! NWListener(using: .tcp, on: Bridge.port())
96+
l.stateUpdateHandler = self.stateDidChange(to:)
97+
l.newConnectionHandler = self.didAccept(nwConnection:)
98+
l.start(queue: .global())
99+
listener = l
100+
}
101+
102+
func reinit() {
103+
print("Server re-init called")
104+
let conn = connectionsByID.first
105+
if conn == nil ||
106+
conn?.value.connection.state == .cancelled {
107+
stopListener()
108+
setupListener()
109+
}
110+
}
111+
112+
static func port() -> NWEndpoint.Port {
113+
return NWEndpoint.Port("23115")!
91114
}
92115

93116
func setEnv(name: String, value: String) {
@@ -105,11 +128,17 @@ class Bridge {
105128
}
106129

107130
func stateDidChange(to newState: NWListener.State) {
131+
print("Server new state: \(newState)")
132+
108133
switch newState {
109134
case .ready:
135+
if erlangStarted {
136+
break
137+
}
138+
erlangStarted = true
110139
print("Bridge Server ready. Starting Elixir")
111140
setEnv(name: "ELIXIR_DESKTOP_OS", value: "ios");
112-
setEnv(name: "BRIDGE_PORT", value: (listener.port?.rawValue.description)!);
141+
setEnv(name: "BRIDGE_PORT", value: (listener?.port?.rawValue.description)!);
113142
// not really the home directory, but persistent between app upgrades (yes?)
114143
setEnv(name: "HOME", value: home.path)
115144
// BINDIR not used on iOS but needs to be defined
@@ -125,7 +154,11 @@ class Bridge {
125154
case .failed(let error):
126155
print("Server failure, error: \(error.localizedDescription)")
127156
exit(EXIT_FAILURE)
157+
case .cancelled:
158+
print("Server failure, cancelled")
159+
exit(EXIT_FAILURE)
128160
default:
161+
print("Server unknown new state: \(newState)")
129162
break
130163
}
131164
}
@@ -137,19 +170,32 @@ class Bridge {
137170
self.connectionDidStop(connection)
138171
}
139172
connection.start()
140-
// connection.send(data: "Welcome you are connection: \(connection.id)".data(using: .utf8)!)
173+
let payload = "\0\0\0\0\0\0\0\0\":reconnect\"".data(using: .utf8)!
174+
175+
let size: UInt32 = CFSwapInt32(UInt32(payload.count))
176+
var message = withUnsafeBytes(of: size) { Data($0) }
177+
message.append(payload)
178+
connection.send(data: message)
141179
print("server did open connection \(connection.id)")
142180
}
143181

144182
private func connectionDidStop(_ connection: ServerConnection) {
145183
self.connectionsByID.removeValue(forKey: connection.id)
146184
print("server did close connection \(connection.id)")
147185
}
186+
187+
private func stopListener() {
188+
if let l = listener {
189+
l.stateUpdateHandler = nil
190+
l.newConnectionHandler = nil
191+
l.cancel()
192+
}
193+
}
148194

149195
private func stop() {
150-
self.listener.stateUpdateHandler = nil
151-
self.listener.newConnectionHandler = nil
152-
self.listener.cancel()
196+
print("stop() called")
197+
198+
stopListener()
153199
for connection in self.connectionsByID.values {
154200
connection.didStopCallback = nil
155201
connection.stop()

todoapp/TodoApp.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,25 @@ import SwiftUI
22

33
@main
44
struct TodoApp: App {
5+
@Environment(\.scenePhase) var scenePhase
6+
57
var content = ContentView()
68
var body: some Scene {
79
WindowGroup {
810
self.content
911
}
12+
.onChange(of: scenePhase) { phase in
13+
switch phase {
14+
case .background:
15+
print(".background")
16+
case .active:
17+
print(".active")
18+
if let bridge = Bridge.instance {
19+
bridge.reinit()
20+
}
21+
default: break
22+
}
23+
}
24+
1025
}
1126
}

0 commit comments

Comments
 (0)