Dzisiaj byłem eksperymentowanie z bloków cel C, tak myślałem, że będę sprytny i dodać do NSArray kilka metod gromadzenia funkcjonalnym stylu, które widziałem w innych językach:Korzystanie z Objective-C Bloki
@interface NSArray (FunWithBlocks)
- (NSArray *)collect:(id (^)(id obj))block;
- (NSArray *)select:(BOOL (^)(id obj))block;
- (NSArray *)flattenedArray;
@end
Metoda collect: pobiera blok, który jest wywoływany dla każdego elementu w tablicy i oczekuje się, że zwróci wyniki operacji wykonanej przy użyciu tego elementu. Rezultatem jest zbieranie wszystkich tych wyników. (Jeśli blok zwróci zero, nic nie zostanie dodane do zestawu wyników).
Metoda select: zwróci nową tablicę zawierającą tylko elementy z oryginału, które po przekazaniu jako argument do bloku zwrócą blok TAK.
I wreszcie, metoda flattenedArray iteruje po elementach tablicy. Jeśli element jest tablicą, rekursywnie wywołuje na nim wartość spłaszczoną i dodaje wyniki do zestawu wyników. Jeśli element nie jest tablicą, dodaje element do zestawu wyników. Zestaw wyników jest zwracany, gdy wszystko jest gotowe.
Teraz, gdy miałem trochę infrastruktury, potrzebowałem testu. Postanowiłem znaleźć wszystkie pliki pakietów w katalogach aplikacji systemu. Oto, co wymyśliłem:
NSArray *packagePaths = [[[NSSearchPathForDirectoriesInDomains(NSAllApplicationsDirectory, NSAllDomainsMask, YES) collect:^(id path) { return (id)[[[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil] collect:^(id file) { return (id)[path stringByAppendingPathComponent:file]; }]; }] flattenedArray] select:^(id fullPath) { return [[NSWorkspace sharedWorkspace] isFilePackageAtPath:fullPath]; }];
Tak - to wszystko jedna linia i jest okropna. Próbowałem kilku podejść do dodawania nowych linii i wcięć, aby spróbować je wyczyścić, ale wciąż wydaje się, że rzeczywisty algorytm jest tracony w całym hałasie. Nie wiem, czy to tylko kwestia składni, czy moje względne doświadczenie w stosowaniu stylu funkcjonalnego, który jest problemem.
Dla porównania, postanowiłem zrobić „staroświecki sposób” i po prostu użyć pętli:
NSMutableArray *packagePaths = [NSMutableArray new];
for (NSString *searchPath in NSSearchPathForDirectoriesInDomains(NSAllApplicationsDirectory, NSAllDomainsMask, YES)) {
for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:searchPath error:nil]) {
NSString *packagePath = [searchPath stringByAppendingPathComponent:file];
if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:packagePath]) {
[packagePaths addObject:packagePath];
}
}
}
IMO ta wersja była łatwiej napisać i jest bardziej czytelny, aby uruchomić.
Przypuszczam, że to możliwe, że był to zły przykład, ale wydaje mi się to uzasadnionym sposobem wykorzystania bloków. (Czy się mylę?) Czy brakuje mi czegoś o tym, jak napisać lub skonstruować kod Objective-C za pomocą bloków, które oczyściłyby ten tekst i uczyniły go jaśniejszym niż (lub nawet tak czystym, jak) zapętloną wersją?
Nicea rozwiązanie, choć nie jestem wielkim fanem redefinicji 'paths' kilkakrotnie. Prawdopodobnie skończyłbym nazywaniem kilku wartości na podstawie ich zawartości, a skończyłbym na jednym o nazwie 'paths'. Tylko moje dwa centy. –
Animacja UIView używa 2 bloków. –
Powiedział, że wzór nie jest kanonem. Te metody, które pobierają wiele bloków, mają bloki jako parametry końcowe. Dodatkowo te API pojawiły się w iOS 4, który był długo po tym wpisie. – logancautrell