web-dev-qa-db-ja.com

次の2行の実行間に遅延を追加する

a(same)関数の2行の実行間に遅延を追加する必要があります。これを行うための好ましいオプションはありますか?

注:これを行うために2つの異なる関数は必要ありません。また、遅延が他の関数の実行に影響してはなりません。

例えば:

line 1: [executing first operation];

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

line 3: [executing second operation];

すべてのヘルプはかなりのものです。前もって感謝します...

69

別のメソッドを作成することなく、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");
});

多くの場合、コードが複雑になり、競合状態が発生する可能性があるため、「本当に遅延を追加する必要があるか」と自問する必要があります。

187
Paul.s

NSThreadメソッドを使用できます。

[NSThread sleepForTimeInterval: delay];

ただし、メインスレッドでこれを行うと、アプリがブロックされるため、バックグラウンドスレッドでのみこれを行います。


またはSwiftの場合

NSThread.sleepForTimeInterval(delay)

in Swift

Thread.sleep(forTimeInterval: delay)
26
Ashley Mills

この行は、3秒後にセレクタsecondMethodを呼び出します。

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

希望する遅延で2回目の操作で使用します。大量のコードがある場合は、独自のメソッドに配置し、performSelector:を使用してそのメソッドを呼び出します。 sleepのようにUIをブロックしません

編集: 2番目のメソッドが必要ない場合は、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);
}
19
Sunkas

ターンベースのゲームがいくつかあり、AIがターンを開始する前に(およびターンのステップ間で)一時停止する必要があります。遅延が最善の解決策である他の、より有用な状況があると確信しています。 Swiftの場合:

        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の呼び出しが異なるかどうかを確認するためにここに戻ってきました(これもその呼び出しに追加する必要があります)。

8
David Reich

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];
});
3
Attila H

@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);
}

メインスレッドまたは現在のスレッドで実行する場合に自分自身を選択したい場合は、これを指定できる特定のメソッドがあります。 Appleのドキュメントには次のように書かれています。

実行ループがデフォルトモード以外のモードにあるときにメッセージをデキューする場合は、代わりにperformSelector:withObject:afterDelay:inModes:メソッドを使用します。現在のスレッドがメインスレッドかどうかわからない場合は、performSelectorOnMainThread:withObject:waitUntilDone:またはperformSelectorOnMainThread:withObject:waitUntilDone:modes:メソッドを使用して、セレクターがメインスレッドで実行されることを保証できます。キューに入れられたメッセージをキャンセルするには、cancelPreviousPerformRequestsWithTarget:またはcancelPreviousPerformRequestsWithTarget:selector:object:メソッドを使用します。

0
Alex Cio