WatchKit 中的解析查询 [英] Parse Query in WatchKit

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

问题描述

我在我的 iPhone 应用程序中执行了一个 Parse 查询,但是我在尝试执行相同的 Parse 查询时遇到了错误我的 Watch 应用.

I do a Parse query in my iPhone app, but I am getting errors trying to do the same Parse query in my Watch app.

这是我的 iPhone 应用中的查询:

- (void)viewDidLoad {
    // GMT Date from Phone
    NSDate *gmtNow = [NSDate date];
    NSLog(@"GMT Now: %@", gmtNow);

    // Query Parse
    PFQuery *query = [self queryForTable];
    [query whereKey:@"dateGame" greaterThanOrEqualTo:gmtNow];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            NSMutableArray *localMatchup = [@[] mutableCopy];

            for (PFObject *object in objects) {
                // Add objects to local Arrays
                [localMatchup addObject:[object objectForKey:@"matchup"]];

                // App Group
                NSString *container = @"group.com.me.off";
                NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:container];

                // Matchup
                [defaults setObject:localMatchup forKey:@"KeyMatchup"];
                NSArray *savedMatchup = [defaults objectForKey:@"KeyMatchup"];
                NSLog(@"Default Matchup: %@", savedMatchup);
                savedMatchup = matchupArray;
            }

            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableView reloadData];
            });

        }
    }];
}

这是我在 WatchKit 应用程序中尝试的查询...

- (void)awakeWithContext:(id)context {
    // GMT Date from Phone
    NSDate *gmtNow = [NSDate date];
    NSLog(@"GMT Now: %@", gmtNow);

    // Query Parse
    PFQuery *query = [self queryForTable];
    [query whereKey:@"dateGame" greaterThanOrEqualTo:gmtNow];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            NSMutableArray *localMatchup = [@[] mutableCopy];

            for (PFObject *object in objects) {
                // Add objects to local Arrays
                [localMatchup addObject:[object objectForKey:@"matchup"]];

                // App Group
                NSString *container = @"group.com.me.off";
                NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:container];

                // Matchup
                [defaults setObject:localMatchup forKey:@"KeyMatchup"];
                NSArray *savedMatchup = [defaults objectForKey:@"KeyMatchup"];
                NSLog(@"Default Matchup: %@", savedMatchup);
                savedMatchup = self.matchupArray;
            }

            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableView reloadData];
            });
        }
    }];
}

但我在这两行中遇到错误...

But I get errors on these two lines...

`PFQuery *query = [self queryForTable];`

`[self.tableView reloadData];`

因为我无法执行与 table 相关的完全相同的代码,我猜,但我只是不确定要将其更改为什么.

because I can't do the same exact code related to a table I'm guessing, but I'm just not sure what to change it to.

为每个@cnoon 答案添加代码

Adding code per @cnoon answer

WatchKit InterfaceController.m:

如何让我的查询在此处运行?- (void)awakeWithContext:(id)context {[超级awakeWithContext:context];

How would I ask for my query to run here? - (void)awakeWithContext:(id)context { [super awakeWithContext:context];

    [WKInterfaceController openParentApplication:nil reply:^(NSDictionary *replyInfo, NSError *error) {
        // What to put here?
        NSLog(@"Open Parent Application");
    }];

-和-

iPhone AppDelegate.h

我如何要求我的 PFQuery 运行?

How would I ask for my PFQuery to run?

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
    // What to put here?
}

推荐答案

WatchKit 应用程序中没有 UITableView 这样的东西.相反,您必须使用 WKInterfaceTable.在继续之前,我还建议您通读 WatchKit 编程指南.作为有抱负的 Apple Watch 开发者,它会让您更好地了解所有可用的工具集.

There's no such thing as a UITableView in a WatchKit application. Instead, you have to work with WKInterfaceTable. Before you continue, I'd also suggest you read through the documentation in the WatchKit Programming Guide. It will give you a MUCH better understanding of all the toolsets available to you as an aspiring Apple Watch developer.

一旦您了解了 WKInterfaceTable 的来龙去脉,您就会很快明白为什么您的方法有缺陷,原因有两个.首先,您没有 reloadData 方法.WatchKit 中的替代方法是 setNumberOfRows(_:withRowTypes:).然后需要遍历每一行并进行配置.

Once you know the ins and outs of a WKInterfaceTable, you'll quickly see why your approach is flawed for two reasons. First off, you don't have a reloadData method. The alternative in WatchKit is to setNumberOfRows(_:withRowTypes:). Then you need to iterate through each row and configure it.

出现问题的第二个原因是您使用了 PFQuery.

The second reason you are going to have issues is due to your use of PFQuery.

这是一些附带建议,所以要么接受要么放弃.我是根据这里的经验说的,我已经构建了一个非常大的基于页面的 Watch 应用程序,该应用程序与 iOS 应用程序进行了大量通信.

This is a bit of side advice, so take it or leave it. I'm speaking from experience here having already built a very large page-based Watch App that heavily communicates with the iOS App.

我建议您停止在 WatchKit 扩展中创建 PFQuery.原因是使用您的 Watch 应用程序的用户只会打开该应用程序一两秒钟.一切都会发生得非常快.正因为如此,在用户终止Watch App之前,很难保证网络调用成功.这让事情变得更加困难,但事实就是如此.

I would advise you to stop making PFQuerys in your WatchKit Extension. The reason is that users using your Watch App are only going to have the app open for a second or two. Everything will happen extremely fast. Because of this, it is extremely difficult to guarantee the success of network calls before the Watch App is terminated by the user. This makes things MUCH more difficult, but is simply the way it is.

相反,您希望在 iOS 应用上运行您的 PFQuery 调用,并通过以下调用将该信息返回给 Watch Extension:

Instead, you want to run your PFQuery calls on the iOS App and return that information back to the Watch Extension through the following calls:

  • WKInterfaceController - openParentApplication(_:reply:)
  • UIApplicationDelegate - handleWatchKitExtensionRequest(_:reply:)

您还可以将 PFQuery 缓存到 共享应用组 使用MMWormhole 或类似的替代方法.下面是一个示例,说明如何让 Watch Extension 请求 iOS 应用程序运行 PFQuery,将数据缓存在 MMWormhole 中并在完成后通知 Watch Extension.通过始终从缓存中读取数据,无论 Watch Extension 是否仍在运行以及是否关闭和重新打开,您都拥有一致的机制.

You can also cache the PFQuery into the shared app group using MMWormhole or a similar approach alternative. Below is an example of how you can have your Watch Extension request the iOS Application to run a PFQuery, cache the data in MMWormhole and notify the Watch Extension once it is finished. By always reading the data out of the cache, you have a consistent mechanism whether the Watch Extension was still running as well as closed and re-opened.

InterfaceController.m

- (void)willActivate {
    [super willActivate];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [WKInterfaceController
         openParentApplication:@{@"pfquery_request": @"dumm_val"}
         reply:^(NSDictionary *replyInfo, NSError *error) {
             NSLog(@"User Info: %@", replyInfo);
             NSLog(@"Error: %@", error);

             if ([replyInfo[@"success"] boolValue]) {
                 NSLog(@"Read data from Wormhole and update interface!");
             }
        }];
    });
}

AppDelegate.m

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
    if (userInfo[@"pfquery_request"]) {
        NSLog(@"Starting PFQuery"); // won't print out to console since you're running the watch extension

        // 1. Run the PFQuery
        // 2. Write the data into MMWormhole (done in PFQuery completion block)
        // 3. Send the reply back to the extension as success (done in PFQuery completion block)

        reply(@{@"success": @(YES)});
    }

    reply(@{@"success": @(NO)});
}

<小时>

迅捷

InterfaceController.swift

override func willActivate() {
    super.willActivate()

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.0 * Float(NSEC_PER_SEC))), dispatch_get_main_queue()) {
        WKInterfaceController.openParentApplication(["pfquery_request": "dummy_val"]) { userInfo, error in
            println("User Info: (userInfo)")
            println("Error: (error)")

            if let success = (userInfo as? [String: AnyObject])?["success"] as? NSNumber {
                if success.boolValue == true {
                    println("Read data from Wormhole and update interface!")
                }
            }
        }

        return
    }
}

AppDelegate.swift

func application(
    application: UIApplication!,
    handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!,
    reply: (([NSObject : AnyObject]!) -> Void)!)
{
    if let pfqueryRequest: AnyObject = (userInfo as? [String: AnyObject])?["pfquery_request"] {
        println("Starting PFQuery") // won't print out to console since you're running the watch extension

        // 1. Run the PFQuery
        // 2. Write the data into MMWormhole (done in PFQuery completion block)
        // 3. Send the reply back to the extension as success (done in PFQuery completion block)

        reply(["success": true])
    }

    reply(["success": false])
}

<小时>

希望这有助于降低以一致的方式从缓存读取数据以及将网络请求(或 PFQueries)卸载到 iOS 应用的复杂性.


Hopefully that helps break down the complexity of having a consistent way to read data from the cache as well as offload network requests (or PFQueries) to the iOS App.

这篇关于WatchKit 中的解析查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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