Objective-C 中的块可以采用 nil 值作为参数吗?
以下代码下载图像并使用块返回结果,以便我可以利用块和 Grand Central Dispatch 的异步功能。我发现如果图像或错误对象为零,我会收到 EXC_BAD_ACCESS 错误。如果参数的值为nil,是否总是会导致错误?
失败的部分是 returnImage 块,它用于在方法末尾返回图像。
- (void)downloadImageWithBlock:(void (^)(UIImage *image, NSError *error))returnImage {
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("Image Downloader Queue", NULL);
dispatch_async(downloadQueue, ^{
UIImage *image = nil;
NSError *error;
// get the UIImage using imageURL (ivar)
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Downloading: %@", imageURL);
});
NSURL *url = [NSURL URLWithString:imageURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLResponse *urlResponse = nil;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
if (!error && response) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Success!");
});
image = [UIImage imageWithData:response];
}
// image will be nil if the request failed
dispatch_async(callerQueue, ^{
returnImage(image, error);
});
});
dispatch_release(downloadQueue);
}
下面是我不知道如何阅读的堆栈跟踪。
0x00002d20 <+0000> push %ebp
0x00002d21 <+0001> mov %esp,%ebp
0x00002d23 <+0003> sub $0x18,%esp
0x00002d26 <+0006> mov 0x8(%ebp),%eax
0x00002d29 <+0009> mov %eax,-0x4(%ebp)
0x00002d2c <+0012> mov -0x4(%ebp),%eax
0x00002d2f <+0015> mov 0x14(%eax),%eax
0x00002d32 <+0018> mov %eax,(%esp)
0x00002d35 <+0021> movl $0x3,0x4(%esp)
0x00002d3d <+0029> call 0x314c <dyld_stub__Block_object_dispose>
0x00002d42 <+0034> mov -0x4(%ebp),%eax
0x00002d45 <+0037> mov 0x18(%eax),%eax
0x00002d48 <+0040> mov %eax,(%esp)
0x00002d4b <+0043> movl $0x3,0x4(%esp)
0x00002d53 <+0051> call 0x314c <dyld_stub__Block_object_dispose>
0x00002d58 <+0056> mov -0x4(%ebp),%eax
0x00002d5b <+0059> mov 0x1c(%eax),%eax
0x00002d5e <+0062> mov %eax,(%esp)
0x00002d61 <+0065> movl $0x7,0x4(%esp)
0x00002d69 <+0073> call 0x314c <dyld_stub__Block_object_dispose>
0x00002d6e <+0078> add $0x18,%esp
0x00002d71 <+0081> pop %ebp
0x00002d72 <+0082> ret
0x00002d73 <+0083> nopw 0x0(%eax,%eax,1)
0x00002d79 <+0089> nopl 0x0(%eax)
The following code that downloads an image and returns the result with a block so that I can take advantage of the async features of blocks and Grand Central Dispatch. I find that if the image or error object is nil I get an EXC_BAD_ACCESS error. Is it always going to cause an error if the value of a parameter is nil?
The part which is failing is the returnImage block which is used to return the image at the end of the method.
- (void)downloadImageWithBlock:(void (^)(UIImage *image, NSError *error))returnImage {
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("Image Downloader Queue", NULL);
dispatch_async(downloadQueue, ^{
UIImage *image = nil;
NSError *error;
// get the UIImage using imageURL (ivar)
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Downloading: %@", imageURL);
});
NSURL *url = [NSURL URLWithString:imageURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLResponse *urlResponse = nil;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
if (!error && response) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Success!");
});
image = [UIImage imageWithData:response];
}
// image will be nil if the request failed
dispatch_async(callerQueue, ^{
returnImage(image, error);
});
});
dispatch_release(downloadQueue);
}
Below is the stack trace which I do not know how to read.
0x00002d20 <+0000> push %ebp
0x00002d21 <+0001> mov %esp,%ebp
0x00002d23 <+0003> sub $0x18,%esp
0x00002d26 <+0006> mov 0x8(%ebp),%eax
0x00002d29 <+0009> mov %eax,-0x4(%ebp)
0x00002d2c <+0012> mov -0x4(%ebp),%eax
0x00002d2f <+0015> mov 0x14(%eax),%eax
0x00002d32 <+0018> mov %eax,(%esp)
0x00002d35 <+0021> movl $0x3,0x4(%esp)
0x00002d3d <+0029> call 0x314c <dyld_stub__Block_object_dispose>
0x00002d42 <+0034> mov -0x4(%ebp),%eax
0x00002d45 <+0037> mov 0x18(%eax),%eax
0x00002d48 <+0040> mov %eax,(%esp)
0x00002d4b <+0043> movl $0x3,0x4(%esp)
0x00002d53 <+0051> call 0x314c <dyld_stub__Block_object_dispose>
0x00002d58 <+0056> mov -0x4(%ebp),%eax
0x00002d5b <+0059> mov 0x1c(%eax),%eax
0x00002d5e <+0062> mov %eax,(%esp)
0x00002d61 <+0065> movl $0x7,0x4(%esp)
0x00002d69 <+0073> call 0x314c <dyld_stub__Block_object_dispose>
0x00002d6e <+0078> add $0x18,%esp
0x00002d71 <+0081> pop %ebp
0x00002d72 <+0082> ret
0x00002d73 <+0083> nopw 0x0(%eax,%eax,1)
0x00002d79 <+0089> nopl 0x0(%eax)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
NSError *error;
创建一个指向随机/无效内存位置的指针。如果块中没有发生错误,则不会为
error
分配新的(有效)值。因此,当您测试error
是否为 nil 时,您将取消引用无效指针:您应该:
更新:在 ARC 下,本地对象变量现在默认为 nil。
NSError *error;
creates a pointer to an random/invalid memory location.If an error does not occur in the block, it will not assign a new (valid) value to
error
. As a result, when you test whethererror
is nil, you are dereferencing an invalid pointer:You should either:
Update: Local object variables now default to nil under ARC.
因此,有几点可能会有所帮助:
您不应该检查错误或对错误做出任何假设,除非响应为零。
如果响应不为零,则错误未定义,但您要求块保留错误。你确定这不是你的问题吗?
您确定 returnImage() 可以处理 nils (或未定义的 NSError *)吗?
So couple of points that may help:
You shouldn't be checking error or make any assumptions about error unless response is nil.
If response is not nil, then error is undefined, and yet you're asking the block to retain error. Are you sure that's not your issue?
Are you sure that returnImage() can handle nils (or an undefined NSError *)?