虽然这个库可以按预期工作,但如果在经常唤醒和休眠的笔记本电脑上使用,经过很长一段时间后,Swift websocket 连接可能会失败,需要自动重启 golang 二进制文件。 这是底层 macOS Swift websockets 库的一个问题。 请考虑使用 calmdocs/SwiftPollManager,它通过 http 长轮询进行通信。
作为构建 electron 应用或使用 GUI 工具包的替代方案,可以运行嵌入在原生 macOS SwiftUI 应用中的 golang 二进制文件。 golang 二进制文件和 SwiftUI 应用通过加密的 websocket 消息进行通信。
如果您已经安装了 xCode 和 go,按照示例构建一个新的运行应用程序大约需要 2 分钟。
创建一个新的 macOS Swift Xcode 项目
运行以下命令
将我们刚刚构建的 gobinary-darwin-amd64 和 gobinary-darwin-arm64 文件拖到我们新的 macOS Swift xCode 项目中。
import SwiftUI
import SwiftStreamManager
import SwiftWebSocketManager
import SwiftProcessManager
public struct CustomStorageItem: Codable, Identifiable {
public var id: Int64
let error: String?
let name: String
let status: String
let progress: Double
enum CodingKeys: String, CodingKey {
case id = "ID"
case error = "Error"
case name = "Name"
case status = "Status"
case progress = "Progress"
}
}
struct ContentView: View {
@ObservedObject var itemsStore: ItemsStore = ItemsStore()
var body: some View {
List {
HStack {
Button(action: {
itemsStore.sm.publish(
itemsStore.sendStream!,
type: "addItem",
id: "",
data: ""
)
}, label: {
Image(systemName: "plus")
})
Spacer()
}
ForEach(itemsStore.items) { item in
HStack{
Text("\(item.name) (\(item.status))")
Spacer()
Button(action: {
itemsStore.sm.publish(
itemsStore.sendStream!,
type: "deleteItem",
id: String(item.id),
data: ""
)
}, label: {
Image(systemName: "trash")
})
}
}
}
}
}
class ItemsStore: ObservableObject {
private let binName = SystemArchitecture() == "arm64" ? "gobinary-darwin-arm64" : "gobinary-darwin-amd64"
@Published var items: [CustomStorageItem] = [CustomStorageItem]()
// StreamManager
@Published var sm: StreamManager
@Published var sendStream: WebSocketStream?
init() {
// Initialise StreamManager
self.sm = StreamManager(
KeyExchange_Curve25519_SHA256_HKDF_AESGCM,
baseURL: URL(string: "ws://127.0.0.1")!,
port: Int.random(in: 8001..<9000)
)
self.sm.addPIDAsArgument("pid")
self.sm.addBearerTokenAsArgument("token")
self.sm.addPortAsArgument("port")
// Start binary and subscribe to a websocket stream
self.sm.subscribeWithBinary(
streamPath: "/ws/0",
binName: self.binName,
withPEMWatcher: true,
standardOutput: { result in
print(result)
},
messages: { message in
// Decrypt and decode
guard let newItems: [CustomStorageItem] = try? self.sm.decryptAndDecodeJSON(
message: message,
auth: self.sm.authTimestamp // Use the current time since 1970 in milliseconds as the default key exchange auth key.
) else {
return
}
// Update items
DispatchQueue.main.async {
self.items.replaceInPlace(items: newItems)
}
},
onConnected: {
// Create a second (sending) stream subscribed to a different path
DispatchQueue.main.async {
self.sendStream = try! self.sm.stream(streamPath: "/ws/1")
self.sm.subscribe(self.sendStream!,
//messages: { message in
// print(message)
//},
errors: { err in
print(err)
}
)
}
}
)
}
}
在创建此库时,我们尽可能保守。 请参阅 calmdocs/SwiftKeyExchange package page 上提供的安全详细信息。 请注意,您使用此库和此 repo 中的代码的风险自负,我们对其使用不承担任何责任。