2013-03-19 7 views
5

Mam metodę, która zwraca blok i inną metodę, która wykorzystuje metodę:iOS: metoda zwraca blok, a następnie blok jest przechowywany w tablicy, kiedy powinienem go skopiować?

- (MyBlock)blockForParameter:(id)param 
{ 
    MyBlock theBlock = ^(){NSLog(@"Param: %@", param);}; 
    return theBlock; 
} 

- (void)methodUser 
{ 
    MyBlock theBlock = [self blockForParameter:something]; 
    [self.allBlocks addObject:theBlock]; 
} 

Powstaje pytanie, kiedy należy skopiować blok? Czy powinienem skopiować ten blok, gdy go zwrócę w blockForParameter, czy powinienem go skopiować po dodaniu do tablicy?

Dzięki

+0

czy w tym przypadku trzeba go skopiować? nowy 'MyBlock' jest tworzony za każdym razem, gdy wywołujesz tę funkcję? Nie jestem ekspertem od bloków, ale to jest to, co myślę, że będzie się działo .. – Fonix

Odpowiedz

3

Bloki muszą być skopiowane gdyby „przeżyć zakres, w jakim zostały one utworzone”, więc należy skopiować blok w metodzie blockForParameter, przed wpuszczeniem go.

Edycja: W ARC nie jest to już prawdą. Zobacz na przykład: Objective-C: blocks in ARC i zawarte w nim odwołania:

  • Zwrócenie bloku z funkcji nie wymaga kopiowania bloku.
  • Dodawanie bloku do kolekcji wymaga wykonania kopii.
+0

afaik, zwracając obiekt, który został utworzony w zakresie, który został zwrócony do innej funkcji, będzie utrzymywał ten obiekt przy życiu nawet po zakończeniu jego pierwotnego zakresu. .. czy blokuje jakiś specjalny przypadek? – Fonix

+0

@Fonix: Bloki są nieco wyjątkowe, ponieważ są tworzone na stosie i muszą zostać przeniesione do sterty, jeśli przekroczą zakres ich tworzenia. –

+0

W przypadku ARC, czy to nie to samo, co po skopiowaniu, gdy zwracam i nie kopiuję go podczas dodawania do kolekcji? – hzxu

1

Przyjrzyj się każdej z metod osobno.

W -blockForParameter: literał bloku jest zwracany z metody. Blok musi zostać skopiowany, aby przeżyć zakres literału. W MRC musisz zwrócić blok skopiowany i autoreleased. W ARC nie musisz nic robić.

W -methodUser blok nie jest zdefiniowany w tej metodzie; jest odbierany z wywołania metody. W związku z tym musi on już zostać skopiowany (tj. Nie jest blokiem stosu). W związku z tym nie musisz nic z nim robić, gdy robisz do niego addObject:.