我使用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;
}
答案 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。