You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WatchOS WCSession无法激活/代理缺失问题求助

WCSession无法激活、watchOS设备不可达的问题修复

问题描述

我尝试在Xcode模拟器中通过Watch Connectivity的WCSession实现iOS应用与watchOS应用的连接,但手表始终显示不可达,会话也无法激活。我使用同一个SyncService类,同时设置iOS和watchOS为目标,并在应用启动的.onAppear方法中初始化它。以下是我的代码:

原SyncService类

import Foundation
import WatchConnectivity

class SyncService : NSObject, WCSessionDelegate {
    
    private var session: WCSession = .default

    init(session: WCSession = .default) {
        super.init()
        self.session = session
        self.session.delegate = self
        print("Reachable :",session.isReachable)
        #if os(iOS)
        print("Connection provider initialized on phone")
        #endif
        #if os(watchOS)
        print("Connection provider initialized on watch")
        #endif
        
        self.connect()
        print("Details",self.session)
    }
    
    func connect() {
        guard WCSession.isSupported() else {
            print("WCSession is not supported")
            return
        }
        switch self.session.activationState {
                case .activated:
                    print("WCSession activated successfully")
                case .inactive:
                    print("Unable to activate the WCSession. Error:")
                case .notActivated:
                    print("Unexpected .notActivated state received after trying to activate the WCSession")
                @unknown default:
                    print("Unexpected state received after trying to activate the WCSession")
                }
        session.activate()
        
    }
    
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        
    }

    #if os(iOS)
    func sessionDidBecomeInactive(_ session: WCSession) { }
    
    func sessionDidDeactivate(_ session: WCSession) { }
    #endif
    
    //   func sendMessage(_ key: String, _ message: String, _ errorHandler: ((Error) -> Void)?) {
    //    if session.isReachable {
    //        session.sendMessage([key : message], replyHandler: nil) { (error) in
    //           print(error.localizedDescription)
    //           if let errorHandler = errorHandler {
    ///             errorHandler(error)
    //        }
    //        }
    //     }
    //     }
}

原iOS应用入口

import SwiftUI

@main
struct ConnectivityApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView() .onAppear{
                var model = SyncService()
            }
        }
    }
}

原watchOS应用入口

import SwiftUI

@main
struct Connectivity_Watch_AppApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView() .onAppear{
                var model = SyncService()
            }
        }
    }
}

核心问题与修复步骤

1. SyncService实例生命周期过短

原代码中,SyncService是在.onAppear闭包内创建的局部变量,闭包执行完毕后实例立即被销毁,导致WCSession还未完成激活就被释放,代理方法无法触发,会话也无法维持激活状态。

  • 修复:在App结构体中持有SyncService实例,保证其生命周期与应用一致。

2. 激活状态检查时机错误

connect()方法中,调用session.activate()前就检查activationState,此时会话还未开始激活,状态必然是.notActivated,这个检查没有实际意义。应在activationDidCompleteWith代理方法中处理激活结果。

3. 未处理激活错误与状态

原activationDidCompleteWith方法为空实现,无法得知激活失败的具体原因,也无法确认激活是否成功。需在此方法中检查错误和最终激活状态。

4. 未监听可达性变化

未实现sessionReachabilityDidChange代理方法,无法实时获取设备的可达状态变化。


修改后的代码

SyncService类(单例模式)

import Foundation
import WatchConnectivity

class SyncService: NSObject, WCSessionDelegate {
    static let shared = SyncService() // 全局单例,保证实例唯一且生命周期稳定
    private let session: WCSession = .default

    private override init() {
        super.init()
        self.session.delegate = self
        #if os(iOS)
        print("Connection provider initialized on phone")
        #endif
        #if os(watchOS)
        print("Connection provider initialized on watch")
        #endif
        connect()
    }
    
    func connect() {
        guard WCSession.isSupported() else {
            print("WCSession is not supported on this device")
            return
        }
        session.activate()
    }
    
    // 处理会话激活结果
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        if let error = error {
            print("WCSession activation failed: \(error.localizedDescription)")
            return
        }
        
        switch activationState {
        case .activated:
            print("WCSession activated successfully")
            print("Initial reachability state: \(session.isReachable)")
        case .inactive:
            print("WCSession is inactive")
        case .notActivated:
            print("WCSession failed to activate")
        @unknown default:
            print("Unexpected WCSession activation state")
        }
    }

    // 监听设备可达性变化
    func sessionReachabilityDidChange(_ session: WCSession) {
        print("Reachability updated: \(session.isReachable)")
    }

    #if os(iOS)
    func sessionDidBecomeInactive(_ session: WCSession) {
        print("WCSession became inactive")
    }
    
    func sessionDidDeactivate(_ session: WCSession) {
        print("WCSession deactivated, reactivating...")
        session.activate() // iOS端会话失效后需重新激活
    }
    #endif
}

iOS应用入口

import SwiftUI

@main
struct ConnectivityApp: App {
    let syncService = SyncService.shared // 持有实例,保证生命周期
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

watchOS应用入口

import SwiftUI

@main
struct Connectivity_Watch_AppApp: App {
    let syncService = SyncService.shared // 持有实例,保证生命周期
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

额外注意事项

  • 确保iOS和watchOS应用的Bundle ID前缀一致,watchOS应用的Bundle ID需为iOS应用的子ID(例如iOS为com.yourname.Connectivity,watchOS为com.yourname.Connectivity.watchkitapp)。
  • 在Xcode模拟器中,需先启动iOS应用,再通过iOS模拟器的Hardware > Watch > Show Watch Home Screen启动watch应用,确保两者处于配对状态。
  • 若模拟器连接异常,可尝试重启Xcode、模拟器,或重置模拟器的内容与设置。

内容的提问来源于stack exchange,提问作者Ahmed Kazez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:50:22