2011-07-28 3 views
4

나는이상한 __block 저장 변수 충돌

NSArray *array = [NSArray arrayWithObjects:@"1", @"2", @"3", nil]; 

__block NSString *a = @"-1"; 

[array enumerateObjectsUsingBlock:^(id whoCares, NSUInteger idx, BOOL *stop) { 
    a = [NSString stringWithFormat:@"%@ %d", a, idx]; 
    NSLog(@"%@", a); 
}]; 

NSLog(@"%@", a); 
이 코드가 작동

다음 (바보) 예를 아래로 증류 한 내 코드에 문제가있다,하지만 난 블록 내에서 첫 번째 NSLog을 (주석 경우) 코드가 충돌합니다. 그러나 형식 문자열을 다음과 같이 변경하면

a = [NSString stringWithFormat:@"%d", idx]; 

코드가 NSLog없이 블록 내에서 올바르게 실행됩니다.

여기에 무슨 일이 일어나고 있습니까? 나는 단지 내가 오해하고 있기를 바란다.

+0

그 코드가 모두 있습니까? –

+1

또한보고있는 특정 충돌이 무엇입니까? –

+0

이것은 내가 실제로하고있는 것의 구성 예입니다. 블록으로 열거하는 배열이 있고 변수 자체를 파생시킨 값으로 변수를 재 할당합니다. 마지막 NSLog에서 잘못된 액세스 오류가 발생했습니다. –

답변

2

stringWithFormat:은 보유하고 있지 않은 자동 렌더링 된 개체를 제공합니다. 블록이 종료되고 NSLog으로 전화 할 때는 a이 이미 할당 해제되었을 수 있습니다.

하나의 솔루션은 변경 가능한 문자열을 사용하고 재 할당하는 대신 매번 추가 할 수 있습니다.

NSArray *array = [NSArray arrayWithObjects:@"1", @"2", @"3", nil]; 

NSMutableString *a = [NSMutableString stringWithFormat:@"-1"]; 

[array enumerateObjectsUsingBlock:^(id whoCares, NSUInteger idx, BOOL *stop) { 
    [a appendFormat:@" %d", idx]; 
}]; 

NSLog(@"%@", a); 
+0

이제 블록이 자신의 범위를 가지고 있다고 생각하지 않아서 바보가되었습니다. 감사합니다. 어쨌든 더 잘 작동하는 변경 가능한 데이터 구조를 사용하도록 솔루션을 이동했습니다. 나는 아직도 계속 진행되고 있었는지 궁금했다. 첫 번째 NSLog가 충돌을 막았다는 사실은 나를 혼란스럽게 만들었지 만 이제는 의미가있다. 감사합니다 –

+1

거의 오른쪽; NSMutableString을 사용한다면'__block'이 필요 없습니다. NSLog()가 충돌을 막았다는 것은 전적으로 우연의 일치이며,이 경우에는 동작이 정의되지 않았기 때문에 의미가 없습니다. :) – bbum

+0

@bbum 옳게 편집 된 __block을 수정 해 주셔서 감사합니다! – zpasternack