![](/img/trans.png)
[英]When does WCSession sendMessage fail to wake iOS app in background?
[英]WatchOS2 WCSession sendMessage doesn't wake iPhone on background
這是在模擬器和真實物理設備iphone5s上進行測試的。 我嘗試使用WCSession sendMessage從WatchOS2擴展到iPhone iOS9代碼進行通信。 當iphone應用程序在前台和后台模式下運行時,它運行良好。
但如果我殺了iPhone應用程序(根本沒有運行應用程序),那么我總是得到errorHandler超時。 所以Watch再也無法與iPhone通信了。
“錯誤域= WCErrorDomain代碼= 7012”消息回復花了太長時間。“UserInfo = {NSLocalizedDescription =消息回復花了太長時間。,NSLocalizedFailureReason =回復超時發生。}”。
我認為它應該在后台喚醒iPhone應用程序。
知道如何解決這個問題或修復它嗎? 謝謝!
在AppDelegate
didFinishLaunchingWithOptions
方法中激活WCSession
非常重要。 你還必須在那里設置WCSessionDelegate
。 如果您在其他地方執行此操作,則在系統在后台啟動被殺應用程序時,可能無法執行代碼。
此外,您應該通過replyHandler
發送回復。 如果你嘗試發送其他東西,系統會等待永遠不會發出的回復。 因此超時錯誤。
這是一個示例,如果它被殺死喚醒應用程序:
在WatchExtension中:
設置會話。 通常在您的ExtensionDelegate中:
func applicationDidFinishLaunching() {
if WCSession.isSupported() {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
}
然后當您需要應用程序中的某些內容時發送消息:
if WCSession.defaultSession().reachable {
let messageDict = ["message": "hello iPhone!"]
WCSession.defaultSession().sendMessage(messageDict, replyHandler: { (replyDict) -> Void in
print(replyDict)
}, errorHandler: { (error) -> Void in
print(error)
}
}
在iPhone App中:
相同的會話設置,但這次也設置了委托:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
...
if WCSession.isSupported() {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
}
然后實現委托方法將回復發送到手表:
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
replyHandler(["message": "Hello Watch!"])
}
只要Watch和iPhone之間存在連接,此功能就可以使用。 如果應用程序未運行,系統將在后台啟動它。
我不知道系統是否會等到你從iCloud收到你的數據,但這個例子肯定會喚醒應用程序。
經過幾個小時的嘗試和@jeron的提示。 我終於弄明白了這個問題。
在我的會話中:didReceiveMessage委托方法,我有兩個調用。 1.replyHandler電話。 2.在我的情況下我運行了一個異步進程(RXPromise),它嵌套了很多RXPromise回調來從雲服務中獲取各種數據。 我沒有注意它,因為它應該立即呼叫並返回。 但是現在我已經將RXPromise塊一起注釋掉,它每次都可以在后台喚醒iOS應用程序。
最后我弄清楚麻煩是因為在RXPromise調用之后,再也不能保證重新回到主線程了。 我相信session:didReceiveMessage必須在主線程上返回。 我沒有在Apple文檔的任何地方看到這提到過。
最終解決方案
- (void)session:(WCSession *)session
didReceiveMessage:(NSDictionary<NSString *, id> *)message
replyHandler:(void (^)(NSDictionary<NSString *, id> *_Nonnull))replyHandler {
replyHandler(@{ @"schedule" : @"OK" });
dispatch_async(dispatch_get_main_queue(), ^{
Nested RXPromise calls.....
});
}
好吧,你可以使用transferUserInfo
來排隊調用。 當app被殺死時,使用sendMessage
會導致錯誤
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.