我有4个方法,每个方法在方法返回之前需要一两秒钟,这些方法返回UIImage,我需要这些图像以最快的方式显示。
-(NSMutableArray*)prepareImages{
UIImage *imageToModifyUsingUIImageCategory;
NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects:
[imageToModifyUsingUIImageCategory doSomethingAndReturn1],
[imageToModifyUsingUIImageCategory doSomethingAndReturn2],
[imageToModifyUsingUIImageCategory doSomethingAndReturn3],
[imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil];
return imageArray;
}
在上面的方法结束时,我将从该数组中获得4个图像。每个“doSomethingAndReturn”方法需要一两秒,这意味着我的prepareImages
方法将完成大约5秒的执行。太久了吧?
我的问题是,还有什么方法可以更快地完成所有这些? GCD是我的选择吗?如何?
非常感谢任何帮助。谢谢!
答案 0 :(得分:16)
假设您不介意在后台顺序加载图像(而不是并行加载),只需简单地调度后台队列即可运行prepareImages
:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSArray *images = [self prepareImages];
// now send the result back to the main thread so we can do
// UIKit stuff
dispatch_async(dispatch_get_main_queue(), ^{
// set the images on your UIImageViews here...
});
});
这会将图像加载到低优先级后台队列中,然后在完成后调度回主线程。
如果您希望保持较低的优先级,可以使用DISPATCH_QUEUE_PRIORITY_BACKGROUND
,但这仅适用于iOS 4.3及更高版本。在这种情况下,您应该检查dispatch_get_global_queue
的返回值,如果它返回0,您可以回退其他优先级之一。
如果要并行加载每个图像,您应该将doSomethingAndReturn
方法转换为NSOperation
子类,并使用NSOperationQueue
来运行它们。这需要更多的努力来实施。如果一次处理多个大图像,请注意内存使用情况。
答案 1 :(得分:1)
我知道如何解决,但尚未经过测试。我正在从我遇到并解决的其他几个问题中得出解决方案:
NSNull
插入NSMutableArray
作为占位符。dispatch_async
繁重的工作并替换NSMutableArray
中的相应条目(使用@synchronized
关键字锁定NSMutableArray
)dispatch async
函数中,向主队列发送更新视图的功能。答案 2 :(得分:1)
您可以使用NSOperationQueue:
NSOperationQueue类调节一组NSOperation对象的执行。添加到队列后,操作将保留在该队列中,直到明确取消或完成其任务为止。队列内的操作(但尚未执行)本身根据优先级和操作间对象依赖性进行组织,并相应地执行。应用程序可以创建多个操作队列并向其中任何一个提交操作。
example for a NSOperationQueue imeplementation
Grand Central Dispatch(GCD)调度队列是执行任务的强大工具。通过调度队列,您可以相对于调用者异步或同步地执行任意代码块。您可以使用调度队列执行几乎所有在单独线程上执行的任务。调度队列的优点是它们比相应的线程代码更易于使用,并且执行这些任务的效率更高。
答案 3 :(得分:1)
您可以在处理器的另一个核心上同时执行以尝试:
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
如果您的处理器有四个核心,则每个方法将在不同的核心上执行。
答案 4 :(得分:0)
我只是将它作为练习:对每个doSomethingAndReturn使用GCD并发Q并使用序列q来监视回调的数量。当回调数等于doSomethingAndReturn(s)的数量时,则返回prepareImages数组。
我创建了代码来测试这个概念。
-(NSString *)doSomethingAndReturn1
{
for (int i=0; i<30; i++)
{
NSLog(@"soSomethingAndReturn1 i: %i", i);
}
return @"soSomethingAndReturn1";
}
-(NSString *)doSomethingAndReturn2
{
for (int i=0; i<10; i++)
{
NSLog(@"soSomethingAndReturn2 i: %i", i);
}
return @"soSomethingAndReturn2";
}
-(NSString *)doSomethingAndReturn3
{
for (int i=0; i<20; i++)
{
NSLog(@"soSomethingAndReturn3 i: %i", i);
}
return @"soSomethingAndReturn3";
}
-(void)addToArray:(NSString *)str
{
[asyncArray addObject:str];
NSLog(@"asyncArray: %@", asyncArray);
}
- (IBAction)buttonMultitasksPressed:(id)sender
{
dispatch_queue_t serialdQueue;
serialdQueue = dispatch_queue_create("com.mydomain.testbed.multimethods", NULL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self addToArray:[self doSomethingAndReturn1]];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self addToArray:[self doSomethingAndReturn2]];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self addToArray:[self doSomethingAndReturn3]];
});
dispatch_sync(serialdQueue, ^{
while (!([asyncArray count] == 3))
{
NSLog(@"not there yet count: %i", [asyncArray count]);
}
});
NSLog(@"end of dispatch_sync serialQueue");
// return asyncArray;
}
编辑:第二个想法:不需要序列号。