Watchkit,带有WatchKit扩展的openParentApplication [英] Watchkit , openParentApplication with WatchKit Extension

查看:88
本文介绍了Watchkit,带有WatchKit扩展的openParentApplication的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第一次无效空" (在iPhone中打开应用程序之前)

First times doesn't work "Null"( before open App in iPhone )

有时不起作用,但是我想要一个循环或计时器来重复此请求以获得结果:

and some times doesn't work but i want one loop or timer for repeat this request for get result :

这是我的代码

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
    // Temporary fix, I hope.
    // --------------------
    __block UIBackgroundTaskIdentifier bogusWorkaroundTask;
    bogusWorkaroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
    });
    // --------------------

    __block UIBackgroundTaskIdentifier realBackgroundTask;
    realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        reply(nil);
        [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
    }];

    // Kick off a network request, heavy processing work, etc.

    // Return any data you need to, obviously.
    // reply(nil);
    reply(@{@"Confirmation" : @"Text was received."});

    [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];

    //  NSLog(@"User Info: %@", userInfo);




}

观看应用代码

- (void)willActivate {
    // This method is called when watch view controller is about to be visible to user
    [super willActivate];




    NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"MyCamande", @"OK", nil];

    [InterfaceController openParentApplication:dictionary reply:^(NSDictionary *replyInfo, NSError *error) {
        NSLog(@"Reply received by Watch app: %@", replyInfo);
    }];

}

如何回忆最终结果

推荐答案

好吧,我不建议您使用任何与手表本身的网络操作有关的东西.首先,因为明显的原因,苹果不建议这样做.手表直接执行的唯一网络操作是加载图像.

Well, I would not recommend you using anything, related to network operations on watch itself. First of all because Apple does not recommend to do it for obvious reasons. The only network thing that is performed on the watch directly is loading images.

我一直在努力地进行网络运营,并等待了大约一周的时间,得出的结论是,目前最稳定的方法尚不明显.

I have been struggling with network operations and watch for like a week and came to a conclusion, that the most stable way to do it right now is not obvious.

主要问题是WKInterfaceController.openParentApplication(...)不能按预期工作.不能只是请求打开iPhone应用程序并按原样返回响应.有大量解决方案指出,在- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply中创建backgound线程可以正常工作,但实际上不行.问题在于此方法必须立即发送reply(...);.即使创建同步请求也无济于事,您将不断收到错误-2 iPhone应用程序未回复..",是10的5倍.

The main issue is that WKInterfaceController.openParentApplication(...) does not work as expected. One can not just request to open iPhone app and give back the response as is. There are tons of solutions stating that creating backgound thread in - (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply would work just fine, but it actually does not. The problem is that this method has to send reply(...); right away. Even creating synchronious requests won't help, you will keep receiving "error -2 iPhone application did not reply.." like 5 times our of 10.

所以,我的解决方法是:

So, my solution is following:

您实现:

func requestUserToken() {
        WKInterfaceController.openParentApplication(["request" : "token"], reply: responseParser)
    }

并解析响应,以获取iPhone没有响应时可能发生的错误.

and parse response for error that might occur if there's no response from iPhone.

在iOS端

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{


    __block UIBackgroundTaskIdentifier watchKitHandler;
    watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
                                                                   expirationHandler:^{
                                                                       watchKitHandler = UIBackgroundTaskInvalid;
                                                                   }];

    NSString *request = userInfo[@"request"];

    if ([request isEqualToString:@"token"])
    {
        reply(@{@"token" : @"OK"});

        [PSWatchNetworkOperations.shared loginUser];
    } 

    dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1 ), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
        [[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
    } );
}

此代码仅创建一个强制iPhone发送网络请求的后台线程.假设您的iPhone应用程序中有一个特殊的类,可以发送这些请求并发送答案以进行观看.目前,仅使用 MMWormhole ,以便在您的应用程序和扩展之间建立通信.该手册非常容易解释.

This code just creates a background thread that forces iPhone to send a network request. Let's imagine you would have a special class in your iPhone app that would send these requests and send the answer to watch. For now, this is only accomplishable using App Groups. So you have to create an app group for your application and watchkit extension. Afterwards, I would recommend using MMWormhole in order to establish communication between your app and extension. The manual is pretty self-explaining.

现在这一切有什么意义.您必须实现向服务器发送请求并通过虫洞发送响应.我使用ReactiveCocoa,因此我代码中的示例如下:

Now what's the point of all this. You have to implement sending request to server and send response through wormhole. I use ReactiveCocoa, so example from my code is like this:

- (void)fetchShoppingLists
{
    RACSignal *signal = [PSHTTPClient.sharedAPIClient rac_GET:@"list/my" parameters:@{@"limit":@20, @"offset":@0} resultClass:PSShoppingListsModel.class];
    [signal subscribeNext:^(PSShoppingListsModel* shoppingLists) {
        [self.wormHole passMessageObject:shoppingLists identifier:@"shoppingLists"];
    }];

    [signal subscribeError:^(NSError *error) {
        [self.wormHole passMessageObject:error identifier:@"error"];
    }];
}

正如您在此处看到的,我发回了响应对象或错误.请注意,您通过虫孔发送的所有邮件都应与NSCoding兼容.

As you see here I send back either response object, or error. Note, that all that you send through wormhole should be NSCoding-compatible.

现在在手表上,您可能会解析如下响应:

Now on the watch you'll probably parse response like this:

override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)

    PSWatchOperations.sharedInstance.requestUserToken()

    PSWatchOperations.sharedInstance.wormhole.listenForMessageWithIdentifier("token", listener: { (messageObject) -> Void in
        // parse message object here
        }
    })

}

因此,要得出一个结论.您将请求发送到父应用程序以从后台唤醒并启动异步操作.立即发送Reply().当您收到操作的答复时,请发送已得到响应的通知.同时,在watchExtension中收听回复.

So, to make a conclusion. You send request to parent application to wake up from background and start async operation. Send reply() back immediately. When you receive answer from operation send notification that you've got response. Meanwhile listen to response in your watchExtension.

对不起,那是很多文字,但是我只是希望它能使人保持冷静,因为我对此花费了很多神经.

Sorry, that was a lot of text, but I just hope it helps keep one's ass cool, because I've spent a lot of nerves on that.

这篇关于Watchkit,带有WatchKit扩展的openParentApplication的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆