我有一个函数,它使用 GCD 在另一个线程中按索引加载图像。
所以让我们假设:
-(void)loadMainImageToIndex:(long)index
{
NSDictionary *dic=[mainData objectAtIndex:index];
NSString *userImageUrl=[dic objectForKey:@"url"];
NSURL *userUrl=[NSURL URLWithString:userImageUrl];
[self downloadImageWithURL:userUrl completionBlock:^(BOOL succeeded, NSData *tdata)
{
if (succeeded)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
{
//do something here
dispatch_async(dispatch_get_main_queue(), ^
{
//do something here that uses the index argument
我调用了这个函数 3 次:
[self loadMainImageToIndex:0];
[self loadMainImageToIndex:1];
[self loadMainImageToIndex:2];
问题是,当第一次调用将结束线程操作时,将进入正题:
dispatch_async(dispatch_get_main_queue()
他会在那里看到
index=0
,或者他会看到最后一个索引是 called (==2)
?问题是,他是否复制了整个函数,所以当他完成时他可以记住启动该方法的参数?
另一件事,同时调用它 3 次,是一种不好的做法吗?
谢谢。
最佳答案
简短版:这里没有问题。你做得很好,它会像你期望的那样表现(每个 block 都有正确的值)。
更长的版本:
-(void)loadMainImageToIndex:(long)index
每次调用此方法都会推送
index
的新副本到堆栈上。当方法返回时,它将被弹出(销毁)。即使这个方法被多次并行调用(在不同的线程上),每个都会有自己的 index
的副本。在自己的堆栈上。局部变量和参数对于方法或函数的每次调用都是私有(private)的。 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
在此处创建 block “捕获”(复制)它在 block 中发现的所有变量。其中包括
index
因为它被以下用户使用:dispatch_async(dispatch_get_main_queue(), ^
所以,这里没有问题。发送到主队列的 block 将拥有自己的
index
副本,它是在创建 block 时制作的。封闭 block 也复制了index
在创建时,该方法复制了传递给它的值作为 index
.请注意,“创建 block 时”是
^{}
的位置。被评估,而不是 dispatch_
函数被调用。这些函数接受一个 block ,它们不创建 block 。创建一个 block 并将其存储在一个变量中然后将该 block 传递给其他东西是完全合法的(也是常见的)。该 block 将在创建时捕获(复制)其变量。这个概念被称为 closure .
关于ios - 编译器是否保存函数的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23829363/