从块内部的变量赋值

时间:2015-01-11 09:45:05

标签: ios objective-c

我使用Swift的Objective-C。我几乎没有客观经验。我尝试使用Apple的示例访问游戏中心,并检索在Swift中使用的前10个排行榜得分。但是,我坚持使用objective-c赋值的基础知识,将检索到的分数数据传回给调用者。有人可以发布一个代码示例来处理这个问题吗?

- (NSArray*) retrieveTopTenScores
{
    GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
    NSArray *temp = nil;
    if (leaderboardRequest != nil)
    {
        leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
        leaderboardRequest.timeScope = GKLeaderboardTimeScopeToday;
        leaderboardRequest.identifier = @"Appid";
        leaderboardRequest.range = NSMakeRange(1,10);
        [leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
            if (error != nil)
            {
                // Handle the error.
                NSLog(@"error in score retrieval");
            }
            if (scores != nil)
            {
               temp = scores; //results to Variable is not assignable (missing __block type specifier)               
            }
        }];
    }
    return temp;

}

4 个答案:

答案 0 :(得分:4)

您的返回值为nil。这是因为loadScoresWithCompletionHandler是一个在后台线程中执行的异步方法,可能需要一些时间来下载数据。在块完成执行之前,执行到达return temp。要保存scores数据,您可以在班级中定义property

@property (nonatomic,strong) NSArray *topTenScores;

然后,您可以在块内分配属性。如果要显示toptenscore,也可以通过在块内部对主线程进行函数调用来更新UI。

[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) 
{
    if (error != nil)
    {
         // Handle the error.
         NSLog(@"error in score retrieval");
    }
    if (scores != nil)
    {
         self.topTenScores = score;
         dispatch_async(dispatch_get_main_queue(), ^{
           // Update the UI on the main thread.
         });
    }
 }];

答案 1 :(得分:2)

您正在调用异步方法,因此您应该采用异步模式。现在最常见的惯例是使用块(就像Apple提供的loadScoresWithCompletionHandler方法一样)。底线,而不是试图立即返回NSArray,而是为您自己的retrieveTopTenScores方法提供一个在请求完成时将被调用的块:

最简单的表现形式如下:

- (void)retrieveTopTenScoresWithCompletionHandler:(void (^)(NSArray *scores, NSError *error))completionHandler
{
    GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];

    if (leaderboardRequest != nil) {
        leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
        leaderboardRequest.timeScope = GKLeaderboardTimeScopeToday;
        leaderboardRequest.identifier = @"Appid";
        leaderboardRequest.range = NSMakeRange(1,10);
        [leaderboardRequest loadScoresWithCompletionHandler:completionHandler];
    }
}

你会这样称呼:

[self retrieveTopTenScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
    if (scores) {
        // use scores array here
    } else {
        //do something with error here

        NSLog(@"retrieveTopTenScoresWithCompletionHandler error: %@", error);
    }
}];

// but do not try to use `scores` here, because the above runs asynchronously
// and thus, we don't have the scores by the time we get here

注意,如果您希望在主队列上运行完成块(如果您正在更新UI或模型对象,这是至关重要的),那么您可能希望执行以下操作(但只需像调用它一样调用它)以上):

- (void)retrieveTopTenScoresWithCompletionHandler:(void (^)(NSArray *scores, NSError *error))completionHandler
{
    GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];

    if (leaderboardRequest != nil) {
        leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
        leaderboardRequest.timeScope = GKLeaderboardTimeScopeToday;
        leaderboardRequest.identifier = @"Appid";
        leaderboardRequest.range = NSMakeRange(1,10);
        [leaderboardRequest loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completionHandler(scores, error);
            });
        }];
    }
}

答案 2 :(得分:0)

最好的是,如果您的主应用程序控制器实现了一种处理排行榜接收的方法,例如:

- (void) handleResultsOfLeaderBoardRequest: (NSArray *) leaderboards error: (NSError *error) {
    // store the list in an attribute or process otherwise
}

然后将调用传递给此方法作为预期排行榜请求的回调处理程序。

答案 3 :(得分:0)

使用块类似于Javascript中的编码。结果数据稍后到达 - 即使在方法完成执行后也是如此。所以你不能返回数组。

loadScoresWithCompletionHandler之后缩进的所有内容:将在/加载分数之后发生。您需要更新该代码块中的UI。