Cocoa touch ARC:从委托方法中使用的内部块获取EXC_BAD_访问权限
我一定是做错了什么,但是自动引用计数文档并没有给我一个提示。我所做的是从委托方法内部使用块回调调用一个方法从块内部访问同一代理会导致访问错误。问题是我传递的对象-loginController正在向其委托发送消息-显然没有释放,当我在块内不访问它时,我可以多次调用该方法而不会出现问题。这是我的密码:Cocoa touch ARC:从委托方法中使用的内部块获取EXC_BAD_访问权限,cocoa-touch,objective-c-blocks,automatic-ref-counting,Cocoa Touch,Objective C Blocks,Automatic Ref Counting,我一定是做错了什么,但是自动引用计数文档并没有给我一个提示。我所做的是从委托方法内部使用块回调调用一个方法从块内部访问同一代理会导致访问错误。问题是我传递的对象-loginController正在向其委托发送消息-显然没有释放,当我在块内不访问它时,我可以多次调用该方法而不会出现问题。这是我的密码: - (void)loginViewDidSubmit:(MyLoginViewController *)loginController { NSString *user = loginCon
- (void)loginViewDidSubmit:(MyLoginViewController *)loginController
{
NSString *user = loginController.usernameLabel.text;
NSString *pass = loginController.passwordLabel.text;
__block MyLoginViewController *theController = loginController;
[self loginUser:user withPassword:pass callback:^(NSString *errorMessage) {
DLog(@"error: %@", errorMessage);
DLog(@"View Controller: %@", theController); // omit this: all good
theController = nil;
}];
}
NSZombieEnabled不记录任何内容,并且没有来自gdb的可用堆栈跟踪。我做错了什么?谢谢你的指点
编辑: 我认为问题的范围更大-上面的回调是从NSURLConnectionLegate方法调用的(块本身是该委托的强属性,因此ARC应该调用block_copy()。在这种情况下,我需要进行特殊测量吗 流程(loginController始终可见): 登录控制器 视图代理 NSURLConnectionLegate
这就是我得到错误访问的地方,但只有当我访问loginController变量时…我想发生的事情是,loginController在调用其委托后就死了。因此会发生崩溃。没有更多信息,我只能想到可能的场景:
我的最佳选择。实际的解决方案是,我将块作为strong属性,但它应该是复制属性!哦
第一个“解决方案”: 我刚刚找到了一种防止坏访问的方法。如我在上面的编辑中所示,视图委托将块转发给httpDelegate(另一个类的实例),httpDelegate反过来保持对块的强引用。无论出于何种原因,将块分配给临时变量并转发临时块变量都可以解决问题。因此: 如前所述,这会在执行块时崩溃 这很有效
我会接受这个答案,如果有人有更多的见解,我很乐意修改我的决定。:) 将copy属性设置为属性,或者只调用块的“copy”方法
- (void)loginUser:(NSString *)user withPassword:(NSString *)pass callback:(void (^callback)(NSString *))
{
callback = [callback copy];
感谢您的拍摄,但不,loginController始终可见。如果我取消对第二个DLog()的注释,我可以按我想要的次数点击“Login”(从同一个loginController的视图),我将始终获得日志,但我在尝试访问发送消息的控制器时遇到了错误的访问。我只是想我的问题可能是别的,回调是从NSURLConnectionLegate异步调用的。也许问题就在这里。。。将更新问题。这是正确的方法。事实上,我已将strong设置为属性属性,但在转换项目时,没有意识到该副本仍然可用。
(method shown above calls the loginUser: method, which does something like:)
httpDelegate.currentCallback = callback;
httpDelegate.currentConnection = // linebreak for readability
[[NSURLConnection alloc] initWithRequest:req
delegate:httpDelegate
startImmediately:YES];
- (void)connection:(NSURLConnection *)aConnection
didFailWithError:(NSError *)error
{
if (NULL != currentCallback) {
currentCallback([error localizedDescription]);
self.currentCallback = NULL;
}
}
httpDelegate.currentCallback = callback;
MyCallbackType aCallback = callback;
httpDelegate.currentCallback = aCallback;
- (void)loginUser:(NSString *)user withPassword:(NSString *)pass callback:(void (^callback)(NSString *))
{
callback = [callback copy];