在 WatchKit 中解析查询

Parse Query in WatchKit

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

这是我的 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];
            });
        }
    }];
}

但是我在这两行中得到了错误...

`PFQuery *query = [self queryForTable];`

`[self.tableView reloadData];`

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

编辑: 根据@cnoon 回答添加代码

WatchKit InterfaceController.m:

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

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

-和-

iPhone AppDelegate.h

我要怎么把我的PFQuery换成运行?

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

WatchKit 应用程序中没有 UITableView 这样的东西。相反,您必须使用 WKInterfaceTable. Before you continue, I'd also suggest you read through the documentation in the WatchKit Programming Guide。作为有抱负的 Apple Watch 开发人员,它会让您更好地了解所有可用的工具集。

WK接口表

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

WatchKit 扩展中的 PFQuery

您遇到问题的第二个原因是您使用了 PFQuery

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 扩展中制作 PFQuerys。原因是使用您的 Watch App 的用户只会打开该应用程序一两秒钟。一切都会发生得非常快。正因为如此,在Watch App被用户终止之前,网络调用的成功是极难保证的。这使事情变得更加困难,但事实就是如此。

相反,您想 运行 您对 iOS 应用程序的 PFQuery 调用,并 return 通过以下调用将该信息返回到 Watch Extension:

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


Objective-C

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)});
}

Swift

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 应用程序的复杂性。