2015-01-11 43 views
0

我使用Swift的Objective-C。我幾乎沒有客觀的經驗。我試圖通過蘋果的例子訪問遊戲中心,並獲得在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

聲明爲'__block的NSArray * TEMP =零;'所以警告會去,但返回值將是空的,因爲你的分數被上載異步方法,因此在得到結果之前執行return語句 –

+0

最好是讓您的主應用程序控制器實現處理結果接收的方法,例如 –

+0

這個設計存在一個根本問題,因爲當這個完成處理程序被稱爲temp時,它已經被返回。 temp只在本地範圍內,即在此方法內。我認爲你應該改變這個方法簽名爲 - (void)。該陣列沒有準備好立即返回。然後按照原樣繼續,但將(此NSArray數據)設置爲iVar或屬性,然後觸發另一個方法來通知返回的結果。 – Jef

回答

3

您的回報值將是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

是的,我剛剛輸入了這個內容時幾乎有同樣的意見。 +1 – Jef

+1

不,「retrieveTopTenScores」沒有業務更新用戶界面。是否擁有擁有最高分數的類屬性的選擇也是完全不同的問題。當然,您可能希望擁有一個帶有分數的類屬性,但這與此方法的異步性質無關。 – Rob

0

最好的是,如果你有你的應用程序主控制器執行處理該排行榜的接收的方法,如:

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

然後,你將調用此方法,因爲回調處理程序的預期的排行榜請求。

-1

使用塊與Javascript中的編碼類似。結果數據稍後到達 - 即使該方法執行完畢。所以你不能返回數組。

loadScoresWithCompletionHandler後面會顯示的所有內容:會在/加載分數後發生。您需要更新該代碼塊內的UI。

1

您正在調用異步方法,因此您應該採用異步模式。現在最常見的慣例是使用塊(就像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或模型對象,這是至關重要的),那麼你可能要像做以下(但j烏斯季調用它像上面一樣):

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