【发布时间】:2021-04-10 03:27:02
【问题描述】:
我的基本要求是在连接到服务器时监听 swift 包的变量值,并在视图模型中更改相同类型的已发布值。
下面的代码是为解释场景而构建的示例代码。此代码无法正常工作,因为连接服务器时isConnected 值未更新。
在示例代码中,一个名为 ClientPackage 的 Swift 包及其类和委托协议。然后是 ViewModel 类,SwiftUI 使用它来更新 UI 的状态,还有一个 LocalClient 类实现 ClientPackage 库。基本上 LocalClient 被用作抽象的本地包,以使 ViewModel 中的实现更容易。 (我不确定这是否是正确的方法。)所以当服务器在ClientPackage 内连接时,我需要更改ViewModel 中的isConnected 布尔值。
所以我想修复此代码以更新 isConencted 值更新。 LocalClient 中的 connected 变量是通过委托方法正确设置的。
如何使ViewModel.connect() 中的关闭工作?
附注在实际应用中,我使用 Starscream 4.0.4 swift 包为ClientPackage。
// SocketClient.swift
// Xcode 12.3
import Foundation
class ViewModel: ObservableObject {
var client: LocalClient?
@Published var isConnected: Bool?
let token = "12345678" // This is fetched async in real scenario
init() {
client = LocalClient(token: token)
}
func connect() {
client?.connect() { connected in
self.isConnected = connected
}
}
}
// Assuming code below is from a local swift package and can be modified
class LocalClient: NSObject {
var coreClient: ClientPackage?
var connected = false
init(token: String) {
super.init()
coreClient = ClientPackage(token: token)
coreClient!.delegate = self
}
func connect(_ completion: @escaping (Bool) -> Void) {
coreClient?.connectToServer()
completion(connected)
}
}
extension LocalClient: ClientPackageDelegate {
func connectedToServer(_ client: ClientPackage) {
connected = true
print("Connected to server")
}
func disconnectedFromServer(_ client: ClientPackage) {
connected = false
print("Disconnected from server")
}
}
// Assuming code below is from a swift package and cannot be modified
// import Starscream
open class ClientPackage {
open weak var delegate: ClientPackageDelegate?
open var socketConnected: Bool?
open var token: String?
public init(token: String) {
self.token = token
self.socketConnected = false
}
open func didConnect() {
self.delegate?.connectedToServer(self)
self.socketConnected = true
}
open func didDisconnect() {
self.delegate?.disconnectedFromServer(self)
self.socketConnected = false
}
open func connectToServer() {
// This method connect client to server asynchronously over websocket
// When connection stable, self.didConnect is called
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.didConnect()
}
}
open func disconnectFromServer() {
// This method disconnect the connection
// When connection stable, self.didDisconnect is called
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.didDisconnect()
}
}
}
public protocol ClientPackageDelegate: NSObjectProtocol {
func connectedToServer(_ client: ClientPackage)
func disconnectedFromServer(_ client: ClientPackage)
}
// ContentView.swift
import SwiftUI
struct ContentView: View {
@StateObject var vm = ViewModel()
var connected: Bool { vm.isConnected ?? false }
var body: some View {
VStack {
Button(connected ? "Disconnected" : "Connected"){
connected ? vm.disconnect() : vm.connect()
}
Text(connected ? "Connected" : "Disconnected")
}
}
}
【问题讨论】:
标签: ios swift asynchronous delegates closures