5

Я хочу использовать переменную __block для получения значения в блоке. Но когда вне блока, переменная __block кажется нулевой. Почему это произойдет?переменная «__block» приводит к нулю при выходе из блока

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; 

Когда я меняю код на [путь к копии], он работает. Но я понятия не имею, хорошая ли это идея. Любое решение?

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

В подобных ситуациях меня радует, что моя команда решила принять ARC. –

ответ

1

Здесь можно использовать копию или сохранить на пути. Причина вашей проблемы заключается в том, что объекты NSString являются членами объектов удобства наряду с другими, такими как NSArray, которые вам фактически не нужно выпускать и уже были автореализованы системой до дней ARC. Лично мне не нравилось, что они это делали, потому что это просто вызвало замешательство. Поскольку блок заканчивает выполнение системы, автореализует строковый объект, который вы выделили, вызывая утечку.

5

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

В частности:

Без АРК, __block также имеет побочный эффект, не сохраняя его содержимое, когда он захвачен блоком. Блоки автоматически сохраняют и освобождают любые указатели объектов, которые они захватывают, но указатели __block имеют специальную обложку и действуют как слабый указатель. Стало распространенной моделью полагаться на это поведение, используя __block, чтобы избежать циклов удержания.

В ARC, __block теперь сохраняет свое содержимое точно так же, как и другие захваченные указатели объектов. Код, который использует __block, чтобы избежать циклов сохранения, больше не будет работать. Вместо этого используйте __weak, как описано выше.

Так что вам нужно скопировать.

+0

Я не верю, что «NSString * path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent: aFileName] - объект, выделенный стеком», является правильным. Насколько я понимаю, только сам объект блока (а не любые объекты, созданные кодом внутри блока) является объектом стека. http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/ –

+0

Вы правы ... спасибо за исправление меня. Я отредактирую свой пост. –

1

Является ли использование блоков даже проблемой здесь?

Мне кажется, что эта последовательность кода:

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

закончилась-рилизинг filePath (потому что вы не владеете результат -stringByAppendingPathComponent:, вы не должны быть (ауто-) выпускать его)

+0

ну, я скопировал неправильный код. Когда я использую «filePath = path», должен возвращать filePath. Затем возникла проблема. Я исправил это сейчас. – Wayne