2012-03-30 49 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