Mam pytanie na temat bezpieczeństwa gwintu poniższym przykładzie kodu firmy Apple (z przewodnikiem programowania GameKit)Modyfikacja zmienny obiekt w przewodnika realizacji
To załadować osiągnięć z centrum gier i zapisać go lokalnie:
Krok 1) Dodaj zmienną właściwość słownika do klasy, która zgłasza osiągnięcia. Słownik ten przechowuje kolekcję obiektów osiągnięć.
@property(nonatomic, retain) NSMutableDictionary *achievementsDictionary;
Krok 2) Zainicjuj słownik osiągnięć.
Krok 3) Zmodyfikuj kod ładujący dane o osiągnięciach, aby dodać obiekty osiągnięć do słownika.
{
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error)
{
if (error == nil)
{
for (GKAchievement* achievement in achievements)
[achievementsDictionary setObject: achievement forKey: achievement.identifier];
}
}];
Moje pytanie wygląda następująco - obiekt achievementmentsDictionary jest modyfikowany w module obsługi zakończenia, bez żadnych blokad sortowania. Czy jest to dozwolone, ponieważ moduły obsługi zakończenia są blokiem pracy, który będzie gwarantowany przez system iOS, który zostanie wykonany jako jednostka w głównym wątku? I nigdy nie napotkasz problemów związanych z bezpieczeństwem wątków?
W innej firmy Apple przykładowy kod (GKTapper), ta część jest obsługiwane w różny sposób:
@property (retain) NSMutableDictionary* earnedAchievementCache; // note this is atomic
Następnie w Handler:
[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;
}
}];
Więc dlaczego inny styl i jest jednym ze sposobów bardziej poprawne niż inne?
dzięki Jeremy. Pytałem również o ogólnie obsługiwane programy obsługi zakończeń bloków. Jeśli dokumentacja nie mówi wprost, gdzie wywoływany jest moduł obsługi zakończenia, czy można bezpiecznie założyć, że nie jest on wywoływany w głównym wątku? Jeśli zostanie określone, aby zostać wywołanym z głównej kolejki, to bezpiecznie jest zrobić cokolwiek w środku, nie martwiąc się o bezpieczeństwo wątków (zakładając, że cały dostęp jest z głównego wątku lub procedury kompilacji zwanej główną kolejką). –
Jeśli nie określa, że twój blok zostanie wywołany w głównej kolejce/wątku, musisz podjąć własne środki, aby upewnić się, że tak jest, jeśli tego właśnie potrzebujesz. Może on zostać wywołany w głównym wątku, ale w tym momencie fakt ten jest szczegółem implementacji, a nie częścią umowy API i może ulec zmianie bez ostrzeżenia. Jeśli zostanie określone, aby zostać wywołanym z głównej kolejki, możesz w pełni to wykorzystać. –
Jedno ostatnie pytanie - jeśli zmienię pierwszy program obsługi zakończenia, aby użyć funkcji dispatch_async (dispatch_get_main_queue(),^{dla (osiągnięcia GKAchievement * w osiągnięciach) [achievementmentsDictionary setObject: achievement forKey: achievement.identifier];});) będzie to Kod może być również bezpieczny dla wątków? Pamiętam, że przeczytałem coś o tym, że nie jest to bezpieczne. –