2012-03-30 31 views
4

我有一个iPhone应用程序,其中我想在后台执行一个方法,每个1秒。iPhone SDK - 在后台线程中运行重复过程

所以在我的主线程,我在我的UIViewControllerviewDidLoad()有以下代码:

[NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(repeatedMethod) userInfo:nil repeats:YES]; 

以下方法:

-(void)repeatedMethod { 
    if(!processIsRunning) { 
    processIsRunning = YES; 
    [self performSelectorInBackground:@selector(runProcessInBackground:) withObject:myImage]; 
    } 
} 

-(void)runProcessInBackground:(UIImage *)image { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    ... Some operations ... 
    ... also call a method on the main thread which sets isProcessRunning to NO 

    [pool release] 
} 

的方式,我有这样的设置,一个新的线程每秒产生一次(除非该进程仍在运行,这要归功于我的processIsRunning标志)。

现在,我的问题是:

(1)这是做到这一点的最好方法是什么?还是有更合适的方式来保留和重用后台线程?

(2)什么可能是最快的方法来做到这一点?每次调用该方法时,我是否都会花时间旋转新的后台线程?

代码可以正常工作,当我在主线程上运行所有内容(我最终不想这么做)时,它会稍微慢一些。

任何建议将是伟大的! 有没有人处理过这类问题?

非常感谢, 布雷特

+0

看看我对这个问题的回答:http://stackoverflow.com/questions/8759264/worker-thread-ios/8759329#8759329 – 2012-03-30 19:27:43

+0

@安德鲁,谢谢!但有一个问题:我怎么能通过一个对象来看待GCD?在我上面的代码中,这个对象是'myImage'。 – Brett 2012-03-30 19:33:53

回答

13

基于对您的评论的问题,我想我会扩大我的意见变成一个真正的答案。你可以使用GCD来做到这一点,这可能是最好的选择。

事情是这样的:

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, backgroundQueue); 
dispatch_source_set_timer(timerSource, dispatch_time(DISPATCH_TIME_NOW, 0), 1.0*NSEC_PER_SEC, 0*NSEC_PER_SEC); 
dispatch_source_set_event_handler(timerSource, ^{ 
    [self repeatedMethod]; 
}); 
dispatch_resume(timerSource); 

- (void)repeatedMethod { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    [self doStuffWithAnImage:self.myImage]; 

    [pool drain]; 
} 

一个最酷的事情有关块是他们捕捉局部范围。这在我上面的例子中没有实际使用,但它使得“传入”对象变成了GCD。看到我对这个问题的回答:Is there an advantage to using blocks over functions in Objective-C?

+0

这实际上很有用!谢谢。但它导致了一个(希望)最后一个问题。在你对另一个问题的参考答案中,你表明该块将在创建时保留本地范围(即,在其他答案中为num1 = 42)。就我而言,我希望self.image不时在主线程上更新。 [self doStuffWithAnImage:self.myImage]是否能够访问最新的图像(由主线程设置),还是保留GCD线程创建时存在的self.image?再次感谢! – Brett 2012-03-30 19:56:44

+0

'self.myImage'相当于'[self myImage]'。由于它实际上正在调用'-myImage'访问器方法,因此它将在该块执行时获取并使用当前值。在任何情况下,该调用都是由该块调用的重复方法进行的。块捕获直接在块体中使用的变量,但它们不会递归地通过所谓的方法递归下降并捕获范围(这是没有意义的,因为方法内的变量在堆栈上,直到方法被称为反正)。所以简而言之,它_will_将获得最新的myImage。 – 2012-03-30 20:01:51

+0

我应该补充一点,您将在一个线程中设置myImage并在另一个线程中读取(也可能设置它)的事实意味着您需要注意线程安全性。只要你只是在后台读取它,而不是设置它,你应该可以简单地通过使@property原子。如果您需要从后台设置它,最简单的方法可能是将调用返回到主线程。 – 2012-03-30 20:03:02