2012-04-09 1 views
3

Objective-C에서^블록을 사용하여 문제가 발생했습니다. 한 블록 내에서 인스턴스 변수를 설정하려고합니다. 주제에 대한 Apple 설명서를 읽었으며 모든 것을 시도한 것 같습니다.^블록에서 속성에 액세스하면 어리석은 행동이 발생합니다.

@interface MyClass 
{ 
    // I have tried all possible combinations using __weak, __strong and __block. 
    __weak __block NSMutableArray *filenames; 
} 

// *.m 
static ASIFormDataRequest *g_request = nil; 

@implementation MyClass 
-(void) funnymethod 
{ 
    filenames = [NSMutableArray array]; 
    [filenames addObject:@"This is a string."]; 
    NSLog(@"%@", filenames); 

    g_request = [InitializerClass initializeRequest]; 
    [g_request setCompletionBlock:^ 
    { 
     filenames = [NSMutableArray array]; 
     [filenames addObject:@"This is another string."]; 
     NSLog(@"%@", filenames); 
    }]; 

    [g_object startASynchronous]; 
} 
@end 

위의 코드는 다음과 같은 출력을 제공한다 : 를 ("이것은 문자열이다.") (NULL) 흡입

. 그래서 __weak, __strong 및 __block의 여러 조합을 시도했으며 그 밖의 다른 결과는 다음과 같습니다. ("이것은 문자열입니다.") ("이것은 다른 문자열입니다.") 그러나! 거대한하지만. 완료 블록은 종료되지 않습니다. 열려있는 연결을 나타내는 위쪽 표시 줄의 활동 표시기가 회전을 계속하고 화면이 응답하지 않게됩니다.

어떻게 블록 내에서 파일 이름 - 개체를 성공적으로 설정할 수 있습니까? 미리 감사드립니다.

+0

완료 블록이 완전히 비어 있으면 어떻게됩니까? ASIFormDataRequest 마무리 문제는이 블록에서 수행중인 작업과 아무런 관련이 없다고 생각합니다. –

답변

4

는 예선은 무엇 :

__block이 한정자는 주어진 변수에 저장된 값을 수정하기 위해 폐쇄를 할 수 있습니다.

__weak이없는 개체에 대한 참조이며 개체가 할당 취소되는 것을 방지합니다.

__strong 인 오브젝트에 대한 참조이므로 오브젝트가 할당 해제되지 않습니다.

당신이해야 할 일은 :

__weak는 현재 범위 종료 후 할당 해제되는 배열을 방지하지 않기 때문에 당신이 원하는 것을하지 않습니다. 비동기 호출을하고 있기 때문에 블록을 실행하기 전에 런타임에서 배열이 사용하는 메모리를 회수하는 데 런타임이 걸리지 않습니다.

__strong은 현재 범위 끝에서 개체를 유지합니다. 이것이 당신이 원하는 것입니다.

__block은 블록이 지정된 변수를 수정할 수 있도록 허용하지만 self이 자동으로 유지되므로 인스턴스 변수를 참조 할 때 필요하지 않습니다.

블록 내에서 Objective-C 개체를 참조 할 때 참조주기 환경에서 기본적으로 유지됩니다. 객체의 인스턴스 변수를 단순히 참조하는 경우에도 마찬가지입니다. 그러나 개체 __block 저장소 유형 수정 자로 표시된 변수는 유지되지 않습니다. 입니다.

참고 : 가비지 수집 환경에서 __weak 및 __block 수정자를 변수에 적용하면 블록이 활성 상태로 유지되지 않습니다.만약 방법의 구현 내에서 블록을 사용하는 경우 객체 인스턴스 변수의 메모리 관리를위한 규칙 미묘한 위치 : 참조 인스턴스 변수에 액세스하는 경우

는 자기 유지된다;

나는 당신의 문제는 (굵은에서 관련 부분을) 여기에있다 생각 :

당신이 가져온 변수가 될 수 있도록 지정할 수 있습니다 변경할 수-즉, __block을 적용하여 읽기 쓰기 금지된다 저장 유형 수정 자. __block 저장소는 로컬 변수의 레지스터, 자동 및 정적 저장소 유형과 비슷하지만 상호 배타적입니다.

__block 변수는 변수의 어휘 범위와 선언 된 모든 블록 및 블록 사본 또는 변수의 어휘 범위 내에서 생성 된 사이에 공유되는 저장소에 있습니다. 따라서, 프레임 내에 선언 된 블록의 사본 (예 : 의 경우 나중에 실행하기 위해 대기열에 포함됨)이 프레임 내에 선언 된 블록 사본이 있으면 스택 프레임이 파괴되어 저장 장치가 저장됩니다 ( ). 주어진 어휘 범위의 복수 블록은 공유 변수 을 동시에 사용할 수 있습니다.

최적화로 블록 저장은 블록 자체와 마찬가지로 스택에서 시작됩니다. 블록이 Block_copy (또는 블록에 사본이 전송 될 때 Objective-C)를 사용하여 복사되는 경우 변수는 힙으로 복사됩니다. 따라서 __block 변수의 주소는 시간 이상 변경 될 수 있습니다. 그들은 가변 길이 배열하지 수 있으며, C99 가변 길이 배열을 포함하는 구조가 될 수 없습니다 :

이 __block 변수에 두 더 제한됩니다.

대신의 NSMutableArray

+ (id)arrayWithObject:(id)anObject를 사용하여 일반 NSArray를 사용해보십시오.

+0

[이 문서의] "가변 길이 배열"(https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502) -CH6-SW1)은 "NSMutableArray"를 의미하는 것이 아니라 [ "C99 variable length array"] (http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html)을 의미합니다. 당신은'__block NSMutableArray *'를 가질 수 있습니다. (여기에는 의미가 없지만 허용됩니다.) –

+0

@KurtRevis가 제거되었습니다. – mydogisbox

+0

ivar을 변경하기 위해'__block'을 사용하지 않아도됩니다. ivars에 대한 액세스는 블록에 의해 복사 된 암시적인 'self' 변수를 거칩니다. 효과적으로 블록은'self-> fileNames = newValue'를 수행합니다. –