我必须做错事,但自动引用计数文档并没有给我一个暗示它可能是什么。我正在做的是从委托方法内部调用带有块回调的方法。 从块内访问同一个代理会导致访问权限不佳。问题是我传递的对象 - loginController 将消息发送给它的委托 - 显然没有发布,当我不在块内访问它时我可以多次调用该方法一个问题。这是我的代码:
- (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没有可用的堆栈跟踪。我在这做错了什么?感谢您的任何指示!
修改
我认为问题的范围更大 - 上面的回调是从NSURLConnectionDelegate方法调用的(块本身是该委托的强属性,因此ARC应该调用Block_copy())。在这种情况下,我是否需要进行特殊测量?
Flow(loginController一直保持可见状态):
[delegate loginViewDidSubmit:self];
(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;
}
}
这是我获取错误访问权限的地方,但只有我访问该loginController变量...
答案 0 :(得分:3)
将copy属性设置为属性,或者只调用块的'copy'方法。
- (void)loginUser:(NSString *)user withPassword:(NSString *)pass callback:(void (^callback)(NSString *))
{
callback = [callback copy];
答案 1 :(得分:1)
实际的解决方案是我将块作为强属性,但它应该是 copy 属性! D'哦!
首先是“解决方案”:
我刚刚找到了一种防止访问不良的方法。如上面的编辑所示, View Delegate 将块转发到httpDelegate(另一个类的实例),而httpDelegate又保留了对该块的强引用。无论出于何种原因,将块分配给临时变量并转发临时块变量都可以解决问题。所以:
httpDelegate.currentCallback = callback;
MyCallbackType aCallback = callback;
httpDelegate.currentCallback = aCallback;
我会接受这个作为答案,如果有人有更多的见解,我很乐意修改我的决定。 :)
答案 2 :(得分:0)
我知道发生了什么,在调用其委托之后,loginController已经死了。因此发生崩溃。没有更多信息,我只能想到可能的情况:
该块不保留loginController对象(__block类型修饰符)。如果该块是异步执行的,那么如果loginController被杀死,则它可能不再可用。因此,无论你想用它做什么,你都无法在块内访问它,应用程序将崩溃。如果控制器在发送loginViewDidSubmit后被终止,则可能发生这种情况。
我认为这很可能是你的情况:loginController调用它的委托对象。委托方法最终同步调用杀死控制器的回调块。调用委托方法后,控制器应该处于活动状态。在委托方法中杀死它很可能会导致崩溃。为了确保这是问题所以,只需在委托方法中使用loginController,并在调用委托后将NSLog语句放入控制器中,不管这个块,你会在那里遇到崩溃。
也许如果您粘贴一些代码,我们可以提供更多帮助。
我最好。