2012-04-23 11 views
5

Chcę użyć zmiennej __block, aby uzyskać wartość w bloku. Ale gdy jest poza blokiem, zmienna __block wydaje się być zerowa. Dlaczego tak się stanie?Zmienna "__block" daje zerową wartość po wyjściu z bloku

NSString *fileName = [Tools MD5Encode:url]; 
    __block NSString *filePath = nil; 
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSString *aFileName = obj; 
     if ([aFileName isEqualToString:fileName]) { 
      NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
      filePath = path; 
      NSLog(@"filePath1 %@", filePath); 
      *stop = YES; 
     } 
    }]; 
    //NSLog(@"filePath2 %@", filePath); 
    //filePath seems to be nil 
    return filePath; 

Po zmianie kodu na [ścieżka kopiowania] działa. Ale nie mam pojęcia, czy to dobry pomysł. Każda decyzja?

NSString *fileName = [Tools MD5Encode:url]; 
    __block NSString *filePath = nil; 
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSString *aFileName = obj; 
     if ([aFileName isEqualToString:fileName]) { 
      NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
      filePath = [path copy]; 
      NSLog(@"filePath1 %@", filePath); 
      *stop = YES; 
     } 
    }]; 
    //NSLog(@"filePath2 %@", filePath); 
    return [filePath autorelease]; 
+1

Takie sytuacje sprawiają, że cieszę się, że mój zespół zdecydował się na ARC. –

Odpowiedz

1

Tu można użyć kopii lub zachować na ścieżce. Powodem twojego problemu jest to, że obiekty NSString są członkami obiektów typu convenience wraz z innymi, takimi jak NSArray, których faktycznie nie musisz wydać i zostały one wcześniej autoreleased przez system przed dniami ARC. Osobiście nie podobało mi się, że zrobili to, ponieważ spowodowało to zamieszanie w ten sposób. Ponieważ blok kończy wykonywanie, system autoreadza obiekt łańcucha, który został przydzielony, powodując wyciek.

5

http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

Konkretnie:

Bez ARC, __block ma również efekt uboczny nie zachowując jego zawartości kiedy jest przechwytywane przez blok. Bloki automatycznie zachowują i zwalniają wszelkie wskaźniki obiektów, które przechwytują, ale wskaźniki __block są specjalne i działają jak słaby wskaźnik. Stało się powszechnym wzorcem polegania na tym zachowaniu za pomocą __block, aby uniknąć cykli zachowywania.

Pod ARC, __block zachowuje teraz swoją zawartość, podobnie jak inne wskaźniki przechwyconego obiektu. Kod, który używa __block do unikania cykli zatrzymania, przestanie działać. Zamiast tego użyj __weak, jak opisano powyżej.

Musisz skopiować.

+0

Nie wierzę, że "NSString * path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent: aFileName] jest obiektem przydzielonym do stosu" jest poprawne. Jak rozumiem, tylko obiekt bloku (nie wszystkie obiekty utworzone przez kod w bloku) jest obiektem stosu. http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/ –

+0

Masz rację ... dzięki za poprawienie mnie. Będę edytować mój post. –

1

Czy korzystanie z bloków jest tu problemem?

Wydaje mi się, że ta sekwencja kodu:

NSString *filePath = nil; 
NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
filePath = path; 
return [filePath autorelease]; 

jest ponad uwalniający filePath (ponieważ nie jesteś właścicielem wynik -stringByAppendingPathComponent:, nie powinno być (auto-) zwalniając go)

+0

cóż, skopiowałem zły kod. Kiedy używam "filePath = path", powinien zwrócić filePath. Potem pojawił się problem. Poprawiłem to teraz. – Wayne

Powiązane problemy