在块IPhone SDK中引用self

时间:2010-07-02 13:43:34

标签: iphone objective-c closures objective-c-blocks self

我正试图建立一个回调机制,我将一个块传递给一个类的init,并在该类调用了一些工作之后。块被调用,大多数都可以工作,除非我在块中的“self”上调用任何东西。我收到程序收到的信号:“EXC_BAD_ACCESS”除非我在块中注释掉对self的任何引用。

我认为我可以在街区内访问自己是错误的吗? 任何建议将不胜感激。这段代码是一个全新的“通用应用程序”,我目前正在研究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];
                         }];

以下是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;
}

和回调电话

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

我改为以下代码行

theCallback = aCallback;

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”,我都会收到可怕的Program接收信号:“EXC_BAD_ACCESS”。我想也许这是一个IOS3.2的东西,所以我尝试在iPhone 4.0模拟器下运行它,结果相同。是否可能需要进行编译器设置才能将块“复制”到堆上?我正在使用LLVM1.5

1 个答案:

答案 0 :(得分:4)

首先,代码中的blockSelf是什么?

其次,不,没有理由不能使用self,这表示代码中存在错误。

具体来说,您没有复制该块。块从堆栈开始。因此,当您说theCallback = aCallback;时,您正在存储对堆栈数据结构的引用。一旦定义的堆栈帧消失,该结构就不再有效。

theCallback = aCallback;更改为theCallback = [aCallback copy];(并将[theCallback release];添加到您的-dealloc方法中。