ios - swift dispatchqueue reference




-performSelector:withObject:afterDelay:?のように、遅延の後にどのようにブロックをトリガーしますか? (12)

BlocksKitフレームワークには素晴らしいものがあります。

BlocksKit

(そしてクラス)

BBlocksKit.m

performSelector:withObject:afterDelay:を使用するのと同じように、遅延の後にプリミティブなパラメータでブロックを呼び出す方法はありますか? int / double / floatような引数を使用しますか?


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で遅れてブロックをトリガーする方法は次のとおりです。

runThisAfterDelay(seconds: 2) { () -> () in
    print("Prints this 2 seconds later in main queue")
}

/// EZSwiftExtensions
func runThisAfterDelay(seconds seconds: Double, after: () -> ()) {
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
    dispatch_after(time, dispatch_get_main_queue(), after)
}

私のレポの標準機能として含まれています。


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)

dispatch_after関数は、指定された期間の後にブロックオブジェクトをディスパッチキューにディスパッチします。 2.0秒後にUI関連のタスクを実行するには、以下のコードを使用してください。

            let delay = 2.0
            let delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
            let mainQueue = dispatch_get_main_queue()

            dispatch_after(delayInNanoSeconds, mainQueue, {

                print("Some UI related task after delay")
            })

迅速に3.0:

            let dispatchTime: DispatchTime = DispatchTime.now() + Double(Int64(2.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
            DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {

          })

Swift 3&Xcode 8.3.2

このコードはあなたに役立ちます、私も説明を追加

// Create custom class, this will make your life easier
class CustomDelay {

    static let cd = CustomDelay()

    // This is your custom delay function
    func runAfterDelay(_ delay:Double, closure:@escaping ()->()) {
        let when = DispatchTime.now() + delay
        DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
    }
}


// here how to use it (Example 1)
class YourViewController: UIViewController {

    // example delay time 2 second
    let delayTime = 2.0

    override func viewDidLoad() {
        super.viewDidLoad()

        CustomDelay.cd.runAfterDelay(delayTime) {
            // This func will run after 2 second
            // Update your UI here, u don't need to worry to bring this to the main thread because your CustomDelay already make this to main thread automatically :)
            self.runFunc()
        }
    }

    // example function 1
    func runFunc() {
        // do your method 1 here
    }
}

// here how to use it (Example 2)
class YourSecondViewController: UIViewController {

    // let say you want to user run function shoot after 3 second they tap a button

    // Create a button (This is programatically, you can create with storyboard too)
    let shootButton: UIButton = {
        let button = UIButton(type: .system)
        button.frame = CGRect(x: 15, y: 15, width: 40, height: 40) // Customize where do you want to put your button inside your ui
        button.setTitle("Shoot", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // create an action selector when user tap shoot button
        shootButton.addTarget(self, action: #selector(shoot), for: .touchUpInside)   
    }

    // example shoot function
    func shoot() {
        // example delay time 3 second then shoot
        let delayTime = 3.0

        // delay a shoot after 3 second
        CustomDelay.cd.runAfterDelay(delayTime) {
            // your shoot method here
            // Update your UI here, u don't need to worry to bring this to the main thread because your CustomDelay already make this to main thread automatically :)
        }
    }   
}

ここでは厄介な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をチェックアウトしてHandySwiftCarthageを使用してプロジェクトに追加し、上記の例とまったく同じように使用できます。

import HandySwift    

delay(bySeconds: 1.5) { 
    // delayed code
}

ここで私の2セント= 5メソッドです;)

私はこれらの詳細をカプセル化し、AppCodeに私の文章の仕方を教えてもらいたい。

void dispatch_after_delay(float delayInSeconds, dispatch_queue_t queue, dispatch_block_t block) {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, queue, block);
}

void dispatch_after_delay_on_main_queue(float delayInSeconds, dispatch_block_t block) {
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_after_delay(delayInSeconds, queue, block);
}

void dispatch_async_on_high_priority_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), block);
}

void dispatch_async_on_background_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}

void dispatch_async_on_main_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_main_queue(), block);
}

独自のクラスで引数をラップするか、プリミティブ型で渡す必要のないメソッドでメソッド呼び出しをラップすることができます。 あなたの遅延後にそのメソッドを呼び出し、そのメソッド内で実行するセレクターを実行します。


私はあなたが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 : https://developer.apple.com/documentation/dispatch/1452876-dispatch_after


迅速な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

}

遅延の後に作業をキューイングするSwift 3の方法は次のとおりです。

DispatchQueue.main.asyncAfter(
  DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
    // do work
}






objective-c-blocks