を使用するのと同じように、遅延後にプリミティブパラメータを使用してブロックを呼び出す方法はありますが、 //のperformSelector:withObject:afterDelay:
ような引数を使用しますか?int
double
float
20 に答える
を探していると思いますdispatch_after()
。ブロックがパラメーターを受け入れないようにする必要がありますが、代わりにブロックがローカル スコープからそれらの変数を取得できるようにすることができます。
int parameter1 = 12;
float parameter2 = 144.1;
// Delay execution of my block for 10 seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
NSLog(@"parameter1: %d parameter2: %f", parameter1, parameter2);
});
詳細: https://developer.apple.com/documentation/dispatch/1452876-dispatch_after
dispatch_after
後でブロックを呼び出すために使用できます。Xcode で、次のように入力dispatch_after
を開始Enter
し、オートコンプリートを押します。
「引数」として 2 つの float を使用した例を次に示します。どのタイプのマクロにも依存する必要はなく、コードの意図は非常に明確です。
スイフト 3、スイフト 4
let time1 = 8.23
let time2 = 3.42
// Delay 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
print("Sum of times: \(time1 + time2)")
}
スイフト2
let time1 = 8.23
let time2 = 3.42
// Delay 2 seconds
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
println("Sum of times: \(time1 + time2)")
}
オブジェクティブ C
CGFloat time1 = 3.49;
CGFloat time2 = 8.13;
// Delay 2 seconds
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CGFloat newTime = time1 + time2;
NSLog(@"New time: %f", newTime);
});
Xcode の組み込みコード スニペット ライブラリを使用するのはどうですか?
スイフトの更新:
多くの賛成票が、この回答を更新するきっかけになりました。
組み込みの Xcode コード スニペット ライブラリには、言語dispatch_after
のみがあります。objective-c
ユーザーは、独自のカスタム コード スニペットを作成することもできますSwift
。
これを Xcode で記述します。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(<#delayInSeconds#> * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), {
<#code to be executed after a specified delay#>
})
このコードをコード スニペット ライブラリ領域にドラッグ アンド ドロップします。
コード スニペット リストの一番下に、 という名前の新しいエンティティがありMy Code Snippet
ます。これをタイトルに編集します。Xcode に入力する際の提案については、Completion Shortcut
.
詳細については、CreatingaCustomCodeSnippet を参照してください。
Swift 3 を更新する
このコードをコード スニペット ライブラリ領域にドラッグ アンド ドロップします。
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(<#delayInSeconds#>)) {
<#code to be executed after a specified delay#>
}
Jaime Cham の回答を拡張して、以下のように NSObject+Blocks カテゴリを作成しました。performSelector:
これらのメソッドは、既存のNSObject メソッドとよりよく一致していると感じました
NSObject+Blocks.h
#import <Foundation/Foundation.h>
@interface NSObject (Blocks)
- (void)performBlock:(void (^)())block afterDelay:(NSTimeInterval)delay;
@end
NSObject+Blocks.m
#import "NSObject+Blocks.h"
@implementation NSObject (Blocks)
- (void)performBlock:(void (^)())block
{
block();
}
- (void)performBlock:(void (^)())block afterDelay:(NSTimeInterval)delay
{
void (^block_)() = [block copy]; // autorelease this if you're not using ARC
[self performSelector:@selector(performBlock:) withObject:block_ afterDelay:delay];
}
@end
そして次のように使用します:
[anyObject performBlock:^{
[anotherObject doYourThings:stuff];
} afterDelay:0.15];
Swift の場合、dispatch_after
メソッドを使用して、特別なものではないグローバル関数を作成しました。読みやすく使いやすいので、私はこれがもっと好きです:
func performBlock(block:() -> Void, afterDelay delay:NSTimeInterval){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), block)
}
次のように使用できます。
performBlock({ () -> Void in
// Perform actions
}, afterDelay: 0.3)
おそらく、どこかのクラス(「Util」など)、またはオブジェクトのカテゴリで、GCDを通過するよりも簡単です。
+ (void)runBlock:(void (^)())block
{
block();
}
+ (void)runAfterDelay:(CGFloat)delay block:(void (^)())block
{
void (^block_)() = [[block copy] autorelease];
[self performSelector:@selector(runBlock:) withObject:block_ afterDelay:delay];
}
使用するには:
[Util runAfterDelay:2 block:^{
NSLog(@"two seconds later!");
}];
迷惑な GCD 呼び出しを何度も行うのを防ぐための便利なヘルパーを次に示します。
public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) {
let dispatchTime = DispatchTime.now() + seconds
dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure)
}
public enum DispatchLevel {
case main, userInteractive, userInitiated, utility, background
var dispatchQueue: DispatchQueue {
switch self {
case .main: return DispatchQueue.main
case .userInteractive: return DispatchQueue.global(qos: .userInteractive)
case .userInitiated: return DispatchQueue.global(qos: .userInitiated)
case .utility: return DispatchQueue.global(qos: .utility)
case .background: return DispatchQueue.global(qos: .background)
}
}
}
次のように、メイン スレッドでコードを遅らせるだけです。
delay(bySeconds: 1.5) {
// delayed code
}
コードを別のスレッドに遅らせたい場合:
delay(bySeconds: 1.5, dispatchLevel: .background) {
// delayed code that will run on background thread
}
より便利な機能も備えたフレームワークが必要な場合は、 HandySwiftをチェックしてください。Carthage を介してプロジェクトに追加し、上記の例とまったく同じように使用できます。
import HandySwift
delay(bySeconds: 1.5) {
// delayed code
}
遅延後に作業をキューに入れる Swift 3 の方法を次に示します。
DispatchQueue.main.asyncAfter(
DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
// do work
}
Swift 3 では、単に DispatchQueue.main.asyncAfter 関数を使用して、「n」秒の遅延後に任意の関数またはアクションをトリガーできます。このコードでは、1 秒後に遅延を設定しています。この関数の本体内で、1 秒の遅延後にトリガーされる任意の関数を呼び出します。
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
// Trigger the function/action after the delay of 1Sec
}
独自のクラスで引数をラップするか、プリミティブ型で渡す必要のないメソッドでメソッド呼び出しをラップすることができます。次に、遅延後にそのメソッドを呼び出し、そのメソッド内で実行したいセレクターを実行します。