From da0a3bf59dc3c78cb588ad4fd81bc79362980139 Mon Sep 17 00:00:00 2001 From: TongTongStudio Date: Mon, 3 Aug 2026 20:51:16 +0800 Subject: [PATCH] =?UTF-8?q?chore(ios):=20=E6=B7=BB=E5=8A=A0LoginView?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E5=A4=8DTokenStore=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E4=B8=8E=E7=BA=BF=E7=A8=8B=E8=B0=83=E5=BA=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Xcode项目中添加LoginView.swift文件引用 - 修复TokenStore中Keychain查询字典类型为CFString - 将DispatchQueue.main.async替换为MainActor.run,避免弱引用丢失 - 修复绑定设备信息时的线程安全与变量命名 --- .../project.pbxproj | 4 ++++ .../Utils/TokenStore.swift | 6 +++--- .../ViewModel/ControllerViewModel.swift | 19 +++++++++++-------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/webrtc_controller_ios/web_rtc_controller_ios.xcodeproj/project.pbxproj b/webrtc_controller_ios/web_rtc_controller_ios.xcodeproj/project.pbxproj index fd7c86c..75572b7 100644 --- a/webrtc_controller_ios/web_rtc_controller_ios.xcodeproj/project.pbxproj +++ b/webrtc_controller_ios/web_rtc_controller_ios.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ FB0000000000000000000012 /* VideoRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0000000000000000000012 /* VideoRecorder.swift */; }; FB0000000000000000000013 /* SetupPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0000000000000000000013 /* SetupPanelView.swift */; }; FB0000000000000000000014 /* ControlPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0000000000000000000014 /* ControlPanelView.swift */; }; + FB0000000000000000000017 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0000000000000000000017 /* LoginView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -53,6 +54,7 @@ FA0000000000000000000012 /* VideoRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRecorder.swift; sourceTree = ""; }; FA0000000000000000000013 /* SetupPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupPanelView.swift; sourceTree = ""; }; FA0000000000000000000014 /* ControlPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlPanelView.swift; sourceTree = ""; }; + FA0000000000000000000017 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -145,6 +147,7 @@ FA0000000000000000000008 /* RemoteTouchView.swift */, FA0000000000000000000009 /* RemoteVideoView.swift */, FA000000000000000000000A /* SelfCodecDisplayView.swift */, + FA0000000000000000000017 /* LoginView.swift */, ); path = Views; sourceTree = ""; @@ -256,6 +259,7 @@ FB0000000000000000000008 /* RemoteTouchView.swift in Sources */, FB0000000000000000000009 /* RemoteVideoView.swift in Sources */, FB000000000000000000000A /* SelfCodecDisplayView.swift in Sources */, + FB0000000000000000000017 /* LoginView.swift in Sources */, FB000000000000000000000B /* ContentView.swift in Sources */, FB000000000000000000000C /* AuthSheetView.swift in Sources */, FB000000000000000000000D /* ControllerViewModel.swift in Sources */, diff --git a/webrtc_controller_ios/web_rtc_controller_ios/Utils/TokenStore.swift b/webrtc_controller_ios/web_rtc_controller_ios/Utils/TokenStore.swift index 2fd85c2..f5a17aa 100644 --- a/webrtc_controller_ios/web_rtc_controller_ios/Utils/TokenStore.swift +++ b/webrtc_controller_ios/web_rtc_controller_ios/Utils/TokenStore.swift @@ -42,7 +42,7 @@ enum TokenStore { static func clear() { for k in [accessKey, refreshKey, userKey] { - let query: [String: Any] = [ + let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: service, kSecAttrAccount: k @@ -55,7 +55,7 @@ enum TokenStore { private static func save(key: String, value: String) { // 先删后存,避免重复条目。 - let query: [String: Any] = [ + let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: service, kSecAttrAccount: key, @@ -66,7 +66,7 @@ enum TokenStore { } private static func load(key: String) -> String? { - let query: [String: Any] = [ + let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: service, kSecAttrAccount: key, diff --git a/webrtc_controller_ios/web_rtc_controller_ios/ViewModel/ControllerViewModel.swift b/webrtc_controller_ios/web_rtc_controller_ios/ViewModel/ControllerViewModel.swift index cdcec03..f5474e8 100644 --- a/webrtc_controller_ios/web_rtc_controller_ios/ViewModel/ControllerViewModel.swift +++ b/webrtc_controller_ios/web_rtc_controller_ios/ViewModel/ControllerViewModel.swift @@ -391,7 +391,8 @@ final class ControllerViewModel: NSObject, ObservableObject { do { let newAt = try await ensureAccessToken() accessToken = newAt - DispatchQueue.main.async { + await MainActor.run { [weak self] in + guard let self else { return } self.signalingClient?.disconnect() self.signalingClient = nil // 用新令牌重建连接(REGISTER_SUCCESS 会再次触发 startWebRTC)。 @@ -403,7 +404,8 @@ final class ControllerViewModel: NSObject, ObservableObject { signaling.connect() } } catch { - DispatchQueue.main.async { + await MainActor.run { [weak self] in + guard let self else { return } self.logout() self.alertMessage = "令牌刷新失败,请重新登录" } @@ -417,13 +419,14 @@ final class ControllerViewModel: NSObject, ObservableObject { do { let data = try await ApiClient.bindings(accessToken: at) guard let list = data["bindings"] as? [[String: Any]], !list.isEmpty else { return } - let uids = list.compactMap { $ -> String? in - if let u = $["deviceUid"] as? String, !u.isEmpty { return u } - return $["deviceId"] as? String + let uids = list.compactMap { entry -> String? in + if let u = entry["deviceUid"] as? String, !u.isEmpty { return u } + return entry["deviceId"] as? String }.filter { !$0.isEmpty } if !uids.isEmpty { - DispatchQueue.main.async { - self.alertMessage = "已绑定设备: " + uids.joined(separator: ", ") + let message = "已绑定设备: " + uids.joined(separator: ", ") + Task { @MainActor [weak self] in + self?.alertMessage = message } } } catch { /* 忽略 */ } @@ -470,7 +473,7 @@ final class ControllerViewModel: NSObject, ObservableObject { webRTCClient?.stats { [weak self] report in guard let self else { return } let text = self.buildStatsText(report) - DispatchQueue.main.async { + Task { @MainActor in self.statsText = text } }