我真的很困惑这个。
这是我的代码:
for (SomeObject *obj in objects) {
[self checkAndDownloadForObject:obj];
}
- (void)checkAndDownloadForObject:(id)obj
{
switch (obj.type) {
开关里面
... switch case scope
NSString *someId = [object.ID copy];
NSInteger random = arc4random();
NSLog(@"working on id=%@", someId);
void (^flock)(NSData *data, NSError *error) = ^(NSData *data, NSError *error) {
NSLog(@"downloaded image for %@ image =%p", someId, data);
NSLog(@"random = %u", random);
[self useDataForId:someId withData:data];
};
NSLog(@"flock %@", flock);
[downloader download:someUrl completionHandler:flock];
void (^aBlock)(int rand) = ^(int rand){
NSLog(@"block ra =%d random %u someId %@", rand, random, someId);
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
int ra = arc4random();
aBlock(ra);
});
// end of switch case scope
当我运行我在日志中看到的代码时:
2014-03-31 17:05:10.741 App[4142:60b] working on id=v7GhDlrq
2014-03-31 17:05:10.742 App[4142:60b] flock <__NSMallocBlock__: 0x17e86e00>
2014-03-31 17:05:10.787 App[4142:60b] working on id=tns_7Z-I
2014-03-31 17:05:10.788 App[4142:60b] flock <__NSMallocBlock__: 0x17ec85c0>
2014-03-31 17:05:10.824 App[4142:60b] downloaded image for v7GhDlrq image =0x18528a00
2014-03-31 17:05:10.825 App[4142:60b] random = 3993203783
2014-03-31 17:05:10.830 App[4142:60b] downloaded image for v7GhDlrq image =0x1852cc00
2014-03-31 17:05:10.831 App[4142:60b] random = 3993203783
2014-03-31 17:05:11.885 App[4142:60b] block ra =-2048013895 random 3993203783 someId v7GhDlrq
2014-03-31 17:05:11.886 App[4142:60b] block ra =513751079 random 727217709 someId tns_7Z-I
因为你可以看到flock
块应该捕获someId
,它在绑定函数的不同调用中是不同的,然后根据它执行某些操作。 aBlock
按预期工作,但flock
始终使用相同的(第一个)someId
。我还给一个随机数进行了仔细检查,然后再次看到第一个值被复制并用于两个调用。
[downloader download:someUrl completionHandler:flock];
方法将flock复制到具有相同块类型的copy属性的对象,然后下载资源然后执行已保存的块。
EDIT1: 如果我传递块文字而不是先变量
[downloader download:someUrl completionHandler:^{
...block
}];
在调试器中,如果我设置了断点,我可以看到该块是 _ NSStackBlock _ ,并且它具有相同的地址(即,这是相同的块文字)调用边界函数。这意味着我收到了与完成处理程序相同的块副本,因此我打印相同的someId
,但在这种情况下出现了一个问题:为什么我会收到相同的堆栈块文字???
请指点我这个代码有什么问题?或者为什么块在我的情况下表现得像那样?
答案 0 :(得分:2)
&#34;为什么我会收到相同的堆栈块文字?&#34;
你不是。
最初,在堆栈上创建块。这个&#34; auto&#34;无论如何,方法返回时变量都不存在。但是,此堆栈块可能/将在download:completionHandler:
内复制。由于循环,新堆栈块很可能会获得相同的地址 - 但它与之前的地址不同,因为那个已被解除分配。
你在日志中看到的,看起来有点奇怪。我也相信,你应该看到someId
的不同值。
在一个简单的测试案例中,我无法重现您的问题。我怀疑其他地方有问题。