2010-07-02 3 views
1

블록의 init에 블록을 전달하는 콜백 메카니즘을 제안하려고합니다. 블록이 호출되면 블록 내에서 "self"를 호출 할 때를 제외하고 대부분 모든 것이 작동합니다. 내가 블록 내에서 자기에 대한 어떤 언급도 언급하지 않는다면, 프로그램 수신 신호 : "EXC_BAD_ACCESS"를 얻는다.블록 내에서 self를 참조하는 것. 아이폰 SDK

내가 블록 내에서 자기에 액세스 할 수 있다고 생각하는 것이 잘못 되었습니까? 조언을 주시면 감사하겠습니다. 이 코드는 새로운 "유니버설 앱"에 포함되어 있으며 현재 IPad 부분에서 작업 중이므로 IPad 시뮬레이터에서 실행됩니다.

일부 코드 : 여기

__block LoginViewController *blockSelf = self; 
    LoginAlertView *alert = [[LoginAlertView alloc] 
         intWithPinPrompt:NO 
         title:@"Mobile Login" 
         myCallback:^(LoginAlertView *v){ 
          DLog(@"self %@", blockSelf); 
          NSString *u = v.userNameText; 
          NSString *p = v.passwordText; 
          NSString *i = v.pinText; 
          [self authenticateUser:u 
              password:p 
               pin:i]; 
         }]; 

하고는 내가 코드

의 라인을 다음과 같이 변경

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ 
if (theCallback) { 
    theCallback(self); 
} 
} 

LoginAlertView

- (id) intWithPinPrompt:(BOOL)pinPromptEnabled title:(NSString*)aTitle myCallback:(loginClicked)aCallback{ 
if (self = [self initWithTitle:aTitle 
         message:nil 
         delegate:self 
      cancelButtonTitle:@"Cancel" 
      otherButtonTitles:@"Login", nil]) { 
    hasPinPrompt = pinPromptEnabled; 
    theCallback = aCallback; 
} 
return self; 
} 

및 콜백 호출에서 일부 코드 다음 오류로 저를 제시

theCallback = [aCallback copy]; 

-

Program received signal: “EXC_BAD_ACCESS”. 
(gdb) bt 
#0 0x029c8c97 in objc_msgSend() 
#1 0xbfffe560 in ??() 
#2 0x00026f66 in -[LoginViewController show] (self=0x4a38450, _cmd=0x209c36c) at LoginViewController.m:18 
#3 0x00026d3b in -[AuthenticatedViewController viewWillAppear:] (self=0x4c1fac0, _cmd=0x20b59ac, animated=0 '\0') at AuthenticatedViewController.m:17 

한 가지, 내 블록의 정의는

typedef void(^loginClicked)(LoginAlertView*); 

와 멤버 변수처럼 보인다 이게

loginClicked theCallback; 

또한 블록 선언을 변수로 옮기고이를 전달하려고 시도했습니다.이 결과는 같았습니다. Bock에서 "copy"를 사용할 때마다 "EXC_BAD_ACCESS"라는 두려운 프로그램 수신 신호가 나타납니다. 아마도 이것이 IOS3.2 일 것이라고 생각했기 때문에 동일한 결과를 iPhone 4.0 시뮬레이터에서 실행 해 보았습니다. 블록을 힙에 "복사"하기 위해 필요한 컴파일러 설정이 있습니까? LLVM1.5를 사용하고 있습니다.

답변

4

먼저 코드에 blockSelf은 무엇입니까?

둘째, 아니요, self을 사용할 수없는 이유가 없습니다. 이는 코드의 버그를 나타냅니다.

특히 블록을 복사하지 않습니다. 블록은 스택에서 시작합니다. 따라서 theCallback = aCallback;이라고 말하면 스택에있는 데이터 구조에 대한 참조가 저장됩니다. 정의 된 스택 프레임이 없어지면 해당 구조는 더 이상 유효하지 않습니다.

변경 theCallback = aCallback;에서 theCallback = [aCallback copy];으로 변경하고 -dealloc 방법에 [theCallback release];을 추가하십시오.

+0

답장을 보내 주셔서 감사합니다 LoginAlert alloc을 호출하기 바로 전에 코드 줄이 있습니다. \t __block LoginViewController * blockSelf = self; 문제가 자체가 변경 가능하지 않고, 스택에서 __block 변수를 사용하지 않으면 블록 내에서 "Const"로만 사용 가능하다면 읽은 내용과 관련이 있는지 확인하려고했습니다. 나는 자기가 스택에 정의되어 있지 않다는 것을 알고 있지만, 나는 그것이 가치있는 일이라고 생각했다. LoginAlertView의 초기화에 "copy"코드를 추가하면 다음과 같은 메시지가 나타납니다. 프로그램 수신 신호 : "EXC_BAD_ACCESS". – Joshua

+0

스택에서 시작하는 블록이며 이것이 문제입니다. 블록을 올바르게 복사 했습니까 (제 대답에 실수가 있었고 콜백을 복사하고 콜백이 아닙니다)? – bbum

+0

오, 그리고, 역 추적 해 봤어? 코드 서식을 얻기 위해 – bbum