1) 업적을 신고하는 클래스에 변경 가능한 사전 속성을 추가합니다. 이 사전은 업적 개체 컬렉션을 저장합니다.
@property(nonatomic, retain) NSMutableDictionary *achievementsDictionary;
2 단계) 업적 사전을 초기화합니다.
achievementsDictionary = [[NSMutableDictionary alloc] init];
3 단계)로드 업적 데이터를로드하는 코드를 수정하여 업적 개체를 사전에 추가합니다.
{
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error)
{
if (error == nil)
{
for (GKAchievement* achievement in achievements)
[achievementsDictionary setObject: achievement forKey: achievement.identifier];
}
}];
내 질문은 다음과 같습니다 .- achievementsDictionary 객체가 정렬 핸들을 잠그지 않고 완료 핸들러에서 수정 중입니다. 완료 핸들러는 iOS가 메인 스레드에서 단위로 실행되도록 보장되는 작업 블록이기 때문에 허용됩니까? 그리고 스레드 안전 문제를 다루지 않습니까? 핸들러에서 다음
@property (retain) NSMutableDictionary* earnedAchievementCache; // note this is atomic
을 : 다른 애플 샘플 코드 (GKTapper)에서
,이 부분은 다르게 처리됩니다[GKAchievement loadAchievementsWithCompletionHandler: ^(NSArray *scores, NSError *error)
{
if(error == NULL)
{
NSMutableDictionary* tempCache= [NSMutableDictionary dictionaryWithCapacity: [scores count]];
for (GKAchievement* score in scores)
{
[tempCache setObject: score forKey: score.identifier];
}
self.earnedAchievementCache= tempCache;
}
}];
왜 다른 스타일, 하나 개의 방법이 더 정확 다른 것보다?
Jeremy에게 감사드립니다. 나는 블록 완성 핸들러에 대해서도 전반적으로 질문했다. 문서에서 완성 처리기가 호출되는 위치를 명시 적으로 밝히지 않으면 기본 스레드에서 호출되지 않는다고 가정하는 것이 안전합니까? 메인 큐에서 호출하도록 지정되면 스레드 안전성에 대한 걱정없이 내부에서 작업을 수행하는 것이 안전합니다 (모든 액세스가 기본 스레드에서 호출되거나 complient 핸들러가 메인 큐에서 호출되었다고 가정). –
블록이 메인 큐/스레드에서 호출되도록 지정하지 않은 경우 필요한 경우 사용자가 직접 조치를 취해야합니다. 실제로는 주 스레드에서 호출 될 수도 있지만 그 시점에서 API 계약의 일부가 아닌 구현 세부 사항이며 경고없이 변경 될 수 있습니다. 기본 대기열에서 호출되도록 지정하면 해당 작업을 최대한 활용할 수 있습니다. –
마지막 질문 하나 - dispatch_async (dispatch_get_main_queue(),^{업적의 GKAchievement * 업적)에 대해 [achievementDictionary setObject : achievement forKey : achievement.identifier];});)를 사용하여 첫 번째 완료 핸들러를 변경하면 이됩니다. 코드가 threadsesafe 수 있습니까? 이것에 대해 무언가를 읽는 것이 안전하지 않다는 것을 기억합니다. –