线程iPhone

时间:2011-01-02 16:34:36

标签: iphone

我有一些像

一样运行的代码

// codeline1 // codeline2

// codeline3(UIMAGE)

// coldline4 // codeline5

如何让代码行3作为单独的线程运行?因此,如果图像需要一段时间才能加载,则其余代码仍会加载。

许多示例使用方法来启动新线程但我希望它在新线程中只运行一行,而不是在另一种方法中。

[self performSelectorOnMainThread:@selector(myMethod) withObject:nil waitUntilDone:NO];
[self performSelectorInBackground:@selector(myMethod) withObject:nil];

2 个答案:

答案 0 :(得分:2)

图像加载的痛苦是(总是?)延迟,直到实际显示图像。它由UI线程显示。因此,即使您在单独的线程中创建UIImage对象,这也将在眨眼间完成,因为没有真正发生的事情(即数据未解压缩),并且解码引起的延迟将延迟UI线程,因为它会尝试显示图像。

除了尝试从后台线程中的图像中读取一个像素,强制它读取整个图像(在后台线程中)之外,我从未真正找到一个好方法。如果您然后在UI线程中显示图像,则图像显示更快,因为UI线程不会受到解码步骤的负担。但请注意,CPU必须以某种方式对事物进行解码,因此当在后台进行解码时,UI交互仍然会有点不稳定。

编辑我必须在这里澄清/纠正自己:解码不会阻止主线程,但会被它延迟。只有在UI线程认为是时候才会解码图像。这可能会干扰您想要提供的用户体验。为避免这种情况,并确保图像已预先加载,您可以尝试在后台读取1个像素。另一种解决方案可能是使用CATiledLayer而不是UIImage方法,但这不是替代品。

答案 1 :(得分:0)

您可以使用GCD

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);
dispatch_async(backgroundQueue, ^{codeline3;}); //unlike performSelectorInBackground:... you can write anything inside the block, not only a single method

如果您需要更新某些UI或其他必须在主线程中完成的事情,您可以调用:

dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue,^{[self doSomethingInThenMainThread];});

来自任何地方,(如果是方法,甚至在codeline3内部),你就完成了;)

这是Apple最有效和最推荐的方式。 (WWDC2010 - 第131节 - iPhone OS中的性能优化) 唯一的缺点是它不能在iOS 2.x或3.x中运行,至少需要4.0。

Standford iPhone Course有关于GCD和多线程的简单和简短示例,何时更改为后台线程以及何时返回主线程。请查看它们以获取更多信息。

希望有所帮助