My WatchKit extension makes heavy use of openParentApplication to load data and images into the WatchKit app, as adviced by Apple. This is working fine, especially after using the clever advice here: http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply
正如Apple所建议的那样,我的WatchKit扩展程序大量使用openParentApplication将数据和图像加载到WatchKit应用程序中。这很好用,特别是在使用这里的聪明建议之后:http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply
However, it's only working for about 15 minutes. After that, the WatchKit extension fails to wake up the iPhone application in the background and the iOS AppDelegate handleWatchKitExtensionRequest is never called. If I manually open the iPhone app, the call gets through and it answers directly to the WatchKit extension, but that is hardly something I can ask the user to do... I want the WatchKit app to usable without having to manually wake up the iOS app every 15 minutes.
但是,它只能工作大约15分钟。之后,WatchKit扩展无法在后台唤醒iPhone应用程序,并且永远不会调用iOS AppDelegate handleWatchKitExtensionRequest。如果我手动打开iPhone应用程序,呼叫就会通过并直接回答WatchKit扩展,但这不是我可以要求用户做的事情...我希望WatchKit应用程序可用而无需手动唤醒iOS应用每15分钟一次。
I'm using iOS 8.2 on the testing device, Swift and Xcode 6.2. Maybe it could be related to using a developer provisioning profile? Anyone else out there having experienced this?
我在测试设备上使用iOS 8.2,Swift和Xcode 6.2。也许它可能与使用开发人员配置文件有关?有没有其他人经历过这个?
Code used in utility class WatchUtils, this is used on several occations in the app:
实用工具类WatchUtils中使用的代码,用于应用程序中的多个部分:
class func openPhoneApp(userInfo: [NSObject : AnyObject], complete:(reply:[NSObject : AnyObject]!, error:NSError!) -> Void) {
WKInterfaceController.openParentApplication(userInfo, reply: { (reply:[NSObject : AnyObject]!, error:NSError!) -> Void in
complete(reply:reply, error:error)
})
}
openPhoneApp is used like this:
openPhoneApp的用法如下:
WatchUtils.openPhoneApp(requestData, complete: { (reply, error) -> Void in
if let reply = reply {
// Do stuff
}
})
AppDelegate:
func application(application: UIApplication!, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!, reply: (([NSObject : AnyObject]!) -> Void)!) {
// Bogus task for keeping app going
var bogusTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
}
// End bogus task after 2 seconds
delay(2.0, closure: { () -> () in
UIApplication.sharedApplication().endBackgroundTask(bogusTask)
})
// Code here for collecting information from phone app
// ...
var replyDict:[NSObject : AnyObject] = ["userHighscore":45]
reply(replyDict)
UIApplication.sharedApplication().endBackgroundTask(bogusTask) // End the bogusTask in case the work was faster than 2 seconds
}
// Utility function for delay
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(),
closure
)
}
1 个解决方案
#1
I had the same problem and reading the docs fixed it for me. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleWatchKitExtensionRequest:reply:
我有同样的问题,阅读文档为我修复它。 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleWatchKitExtensionRequest:reply:
Because this method is likely to be called while your app is in the background, call the beginBackgroundTaskWithName:expirationHandler: method at the start of your implementation and the endBackgroundTask: method after you have processed the reply and executed the reply block. Starting a background task ensures that your app is not suspended before it has a chance to send its reply.
因为在您的应用程序在后台时可能会调用此方法,所以在执行开始时调用beginBackgroundTaskWithName:expirationHandler:方法,并在处理完回复并执行回复块后调用endBackgroundTask:方法。启动后台任务可确保您的应用在有机会发送回复之前不会被暂停。
Some of my code:
我的一些代码:
nint taskId = 0;
public override void HandleWatchKitExtensionRequest (UIApplication application, NSDictionary userInfo, Action<NSDictionary> reply)
{
try {
taskId= UIApplication.SharedApplication.BeginBackgroundTask(delegate
{ //this is the action that will run when the task expires
});
if (userInfo != null && userInfo.Keys [0] != null && userInfo.Keys [0].ToString() == "match") {
MyWebClient wc = new MyWebClient ();
wc.Encoding = Encoding.UTF8;
wc.DownloadStringCompleted += (object sender, DownloadStringCompletedEventArgs e) => {
String res = e.Result;
reply (new NSDictionary (
"justTesting", new NSString (res)
));
if(taskId != 0)
UIApplication.SharedApplication.EndBackgroundTask(taskId);
};
wc.DownloadStringAsync(new Uri(myUrl));
}
}
After I changed to doing this it has been rock stable for days for me while previously it always stopped working after 5-15 minutes.
在我改变这样做之后,它已经稳定了几天,而以前它总是在5-15分钟后停止工作。
#1
I had the same problem and reading the docs fixed it for me. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleWatchKitExtensionRequest:reply:
我有同样的问题,阅读文档为我修复它。 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleWatchKitExtensionRequest:reply:
Because this method is likely to be called while your app is in the background, call the beginBackgroundTaskWithName:expirationHandler: method at the start of your implementation and the endBackgroundTask: method after you have processed the reply and executed the reply block. Starting a background task ensures that your app is not suspended before it has a chance to send its reply.
因为在您的应用程序在后台时可能会调用此方法,所以在执行开始时调用beginBackgroundTaskWithName:expirationHandler:方法,并在处理完回复并执行回复块后调用endBackgroundTask:方法。启动后台任务可确保您的应用在有机会发送回复之前不会被暂停。
Some of my code:
我的一些代码:
nint taskId = 0;
public override void HandleWatchKitExtensionRequest (UIApplication application, NSDictionary userInfo, Action<NSDictionary> reply)
{
try {
taskId= UIApplication.SharedApplication.BeginBackgroundTask(delegate
{ //this is the action that will run when the task expires
});
if (userInfo != null && userInfo.Keys [0] != null && userInfo.Keys [0].ToString() == "match") {
MyWebClient wc = new MyWebClient ();
wc.Encoding = Encoding.UTF8;
wc.DownloadStringCompleted += (object sender, DownloadStringCompletedEventArgs e) => {
String res = e.Result;
reply (new NSDictionary (
"justTesting", new NSString (res)
));
if(taskId != 0)
UIApplication.SharedApplication.EndBackgroundTask(taskId);
};
wc.DownloadStringAsync(new Uri(myUrl));
}
}
After I changed to doing this it has been rock stable for days for me while previously it always stopped working after 5-15 minutes.
在我改变这样做之后,它已经稳定了几天,而以前它总是在5-15分钟后停止工作。