我对iOS中的GCD和队列组合几乎没有疑问。让我把这些放在这里
首先。根据IOS6编程cookbook,这里是使用异步和同步下载图像的小代码片段。及其如下
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_async (concurrentQueue, ^ {
UIImage *image = nil;
dispatch_sync(concurrentQueue, ^ { /* download image here */ });
dispatch_sync(dispatch_get_main_queue, ^ { /* show the downloaded image here */ });
});
二。我需要从Url下载一些图像,同时我需要更新进度视图,显示已下载了多少图像。所以我使用下面的代码片段
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async (concurrentQueue, ^ { dispatch_sync(dispatch_get_main_queue, ^ { /* download image here and update progress view here */ });
});
请注意,我正在更新主线程上的进度视图。但是在下载完所有图像后,我的进度视图会显示出来。我检查了其他链接,但不清楚答案。没有得到问题的原因。我的代码如下。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_sync(dispatch_get_main_queue(), ^{
alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
prgView.frame = CGRectMake(10, 50, 270, 20);
[alert addSubview:prgView];
[alert show];
prgView.progress=0.0;
actual= 0.0;
for(NSInteger i=0; i<[fileLinks count];i++)
{
// [self downLoadFileFromUrl : fileLinks[i]: i ];
NSLog(@"Url is %@", fileLinks[i]);
NSLog(@"i value is %d", i);
NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
NSString * _filename= [fileLinks[i] lastPathComponent];
NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
[filePath appendString: _filename] ;
[imagedata writeToFile: filePath atomically:YES];
prgView.progress =((float) i /([fileLinks count]));
NSLog(@" progress value is %f", prgView.progress);
}
});
});
那么这里有什么问题?而另一个疑问是,如果任何人想要在执行长处理任务时持有用户(显示进度视图或活动指示符),他们不能在主线程中这样做吗? (如果他们正在显示进度条或活动指示符),为什么我们必须使用异步,同步线程或主线程等的组合等。
我有点困惑,因为我必须使用异步,同步,主队列,并发队列,串行队列的正确组合。如果任何一个给我解释我或提供了良好的链接,了解异步,同步和3队列的组合。这将是伟大的。
答案 0 :(得分:2)
您应该在主队列
上创建和更新`UIProgressView'并在另一个队列(非主队列)上完成工作
在做你的工作时,如果你想更新GUI上的任何对象,你应该在主队列上进行
你可以这样做:
alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
prgView.frame = CGRectMake(10, 50, 270, 20);
[alert addSubview:prgView];
[alert show];
prgView.progress=0.0;
actual= 0.0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for(NSInteger i=0; i<[fileLinks count];i++)
{
// [self downLoadFileFromUrl : fileLinks[i]: i ];
NSLog(@"Url is %@", fileLinks[i]);
NSLog(@"i value is %d", i);
NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
NSString * _filename= [fileLinks[i] lastPathComponent];
NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
[filePath appendString: _filename] ;
[imagedata writeToFile: filePath atomically:YES];
dispatch_async(dispatch_get_main_queue(), ^{
prgView.progress =((float) i /([fileLinks count]));
});
NSLog(@" progress value is %f", prgView.progress);
}
});
你可以阅读一本电子书:“Pro.Multithreading.and.Memory.Management.for.iOS.and.OS.X”(买或问gg)
祝你好运!答案 1 :(得分:0)
异步和同步的组合是正确的,但是主线程和其他线程的组合导致循环,特别是在使用同步主线程的异步线程中。
答案 2 :(得分:0)
如果你仔细看看你的代码,你会注意到你实际上在主线程中运行了所有内容。
^{dispatch_sync(dispatch_get_main_queue(), ^{
alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
prgView.frame = CGRectMake(10, 50, 270, 20);
[alert addSubview:prgView];
[alert show];
prgView.progress=0.0;
actual= 0.0;
for(NSInteger i=0; i<[fileLinks count];i++)
{
// [self downLoadFileFromUrl : fileLinks[i]: i ];
NSLog(@"Url is %@", fileLinks[i]);
NSLog(@"i value is %d", i);
NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
NSString * _filename= [fileLinks[i] lastPathComponent];
NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
[filePath appendString: _filename] ;
[imagedata writeToFile: filePath atomically:YES];
prgView.progress =((float) i /([fileLinks count]));
NSLog(@" progress value is %f", prgView.progress);
}
});
这将运行downloadFileFromUrl并更新主线程中的进度视图(除非downloadFileFromUrl是异步操作,我不知道)
基本上你需要在辅助线程中运行downloadFileFromUrl方法,然后只在主线程上运行这个位:prgView.progress =((float)i /([fileLinks count]));