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

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

问题描述

第一次不起作用Null"(在 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);
    }];

}

如何回忆得到最终结果

推荐答案

好吧,我不建议您使用任何与手表本身的网络操作相关的东西.首先,因为显而易见的原因,Apple 不建议这样做.在手表上直接执行的唯一网络事情是加载图像.

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 中创建后台线程会工作得很好,但实际上并没有.问题是这个方法必须立即发送 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 应用程序中有一个特殊的类,它将发送这些请求并发送答案以供观看.目前,这只能使用 应用组.所以你必须为你的应用程序和 watchkit 扩展创建一个应用程序组.之后,我建议使用 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
        }
    })

}

所以,得出一个结论.您向父应用程序发送请求以从后台唤醒并开始异步操作.立即发送回复().当您收到操作的答复时,请发送您已收到答复的通知.同时在 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天全站免登陆