2013-03-11 63 views
57

我需要在(相同)函數中執行兩行之間添加延遲。是否有任何有利的選擇來做到這一點?在執行下面兩行之間添加延遲

注意:我不需要兩個不同的函數來做到這一點,並且延遲不得影響其他函數的執行。

如:

line 1: [executing first operation]; 

line 2: Delay      /* I need to introduce delay here */ 

line 3: [executing second operation]; 

任何幫助是明顯的。在此先感謝...

回答

149

您可以使用GCD要做到這一點,而無需創建另一個方法

double delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    NSLog(@"Do some work"); 
}); 

你還是應該問自己「我真的需要添加一個延遲」,因爲它往往可以複雜代碼,並導致競爭條件

+2

向人們警告這是正確的,但是如果您編碼的控制器需要等待外部設備進行固定的處理時間,則它不是無意義的。 – user2161301 2015-10-02 11:55:41

+2

如何在寫入搜索欄時延遲HTTP請求?在輸入時過濾結果?在請求一個過濾列表之前等待一秒鐘,而不是向服務器查詢用戶點擊的每個按鍵,這聽起來對我來說並不是什麼廢話。 – 2016-07-15 17:00:50

17

這條線在3秒後調用選擇secondMethod:

[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ]; 

與你期望的延遲使用它在你的第二個操作。如果您有很多代碼,請將其置於其自己的方法中,並使用performSelector:調用該方法。它不會阻止像sleep

編輯UI:如果你不想讓你可以添加一個類別中的第二種方法可以使用塊與performSelector:

@implementation NSObject (PerformBlockAfterDelay) 

- (void)performBlock:(void (^)(void))block 
      afterDelay:(NSTimeInterval)delay 
{ 
    block = [block copy]; 
    [self performSelector:@selector(fireBlockAfterDelay:) 
       withObject:block 
       afterDelay:delay]; 
} 

- (void)fireBlockAfterDelay:(void (^)(void))block 
{ 
    block(); 
} 

@end 

或許更清潔:

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void)) 
{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay), 
     dispatch_get_current_queue(), block); 
} 
+6

的OP明確指出他們不希望第二個方法:S – 2013-03-11 10:10:47

+0

他可以添加一個類別,能夠使用塊用'performSelector':http://stackoverflow.com/questions/4007023/blocks-instead - 執行selectorwithobjectafterlaylay – Sunkas 2013-03-11 10:31:22

+0

@Sunkas:謝謝你的答案。但我已經提到過我不想添加第二個函數。 – 2013-03-11 12:09:38

2

如果你的目標的iOS 4.0及以上版本,你可以做到以下幾點:

[executing first operation]; 
double delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [executing second operation]; 
}); 
+1

你的意思是iOS 4? [Grand central dispatch Function Reference](http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2-SW3) – 2013-03-11 10:47:31

23

可以使用NSThread方法:

[NSThread sleepForTimeInterval: delay]; 

但是,如果你這樣做,你會阻止應用程序的主線程上,所以只能這樣做在後臺線程。


或斯威夫特

NSThread.sleepForTimeInterval(delay) 

斯威夫特卡倫特3

Thread.sleep(forTimeInterval: delay) 
+0

我相信這應該是根據問題要求接受的答案。 – ACLima 2016-04-05 23:06:52

+1

@ACLima:對不起,'sleepForTimeInterval'會將線程休眠一段給定的時間間隔,這可能會影響其他同時執行的函數。 – 2016-04-15 07:18:19

+0

@KrishnaRajSalim我明白了,謝謝 – ACLima 2016-04-15 10:01:54

8

我有一對夫婦的回合制遊戲,我需要的AI服用之前暫停其轉(在輪到它之間)。我敢肯定還有其他更有用的情況,其中延遲是最好的解決方案。在斯威夫特:

 let delay = 2.0 * Double(NSEC_PER_SEC) 
     let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) 
     dispatch_after(time, dispatch_get_main_queue()) { self.playerTapped(aiPlayView) } 

我剛回來這裏看看Objective-C的電話都是不同的(我需要這個添加到一個,太。)

0

Like @Sunkas寫道,performSelector:withObject:afterDelay:dispatch_after的吊墜,只是它更短,而且具有正常的objective-c語法。如果你需要傳遞參數給希望延遲塊,你可以通過他們通過參數withObject,您將收到它在selector你撥打:

[self performSelector:@selector(testStringMethod:) 
      withObject:@"Test Test" 
      afterDelay:0.5]; 

- (void)testStringMethod:(NSString *)string{ 
    NSLog(@"string >>> %@", string); 
} 

如果你仍然想如果要自己選擇你在主線程或當前線程上執行它,有一些特定的方法可以讓你指定它。蘋果文檔講述了這樣:

如果您希望在運行循環是在默認模式以外的模式 出隊的消息,使用 performSelector:withObject:afterDelay:inModes:方法來代替。如果 不確定當前線程是否爲主線程,則可以使用performSelectorOnMainThread:withObject:waitUntilDone:或 執行selectSelectorOnMainThread:withObject:waitUntilDone:modes:方法到 保證您的選擇器在主線程上執行。要取消排隊的消息,請使用cancelPreviousPerformRequestsWithTarget:或者 cancelPreviousPerformRequestsWithTarget:selector:object:method。