How do you trigger a block after a delay, like -pe

2019-01-01 02:53发布

Is there a way to call a block with a primitive parameter after a delay, like using performSelector:withObject:afterDelay: but with an argument like int/double/float?

17条回答
春风洒进眼中
2楼-- · 2019-01-01 03:02

I think you're looking for dispatch_after(). It requires your block to accept no parameters, but you can just let the block capture those variables from your local scope instead.

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

More: https://developer.apple.com/documentation/dispatch/1452876-dispatch_after

查看更多
妖精总统
3楼-- · 2019-01-01 03:02

You can use dispatch_after to call a block later. In Xcode, start typing dispatch_after and hit Enter to autocomplete to the following:

enter image description here

Here's an example with two floats as "arguments." You don't have to rely on any type of macro, and the intent of the code is quite clear:

Swift 3, Swift 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)")
}

Swift 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)")
}

Objective 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);
});
查看更多
大哥的爱人
4楼-- · 2019-01-01 03:06

How about using Xcode built-in code snippet library?

enter image description here

Update for Swift:

Many up votes inspired me to update this answer.

The build-in Xcode code snippet library has dispatch_after for only objective-c language. People can also create their own Custom Code Snippet for Swift.

Write this in 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#>
    })

Drag this code and drop it in the code snippet library area. enter image description here

Bottom of the code snippet list, there will be a new entity named My Code Snippet. Edit this for a title. For suggestion as you type in the Xcode fill in the Completion Shortcut.

For more info see CreatingaCustomCodeSnippet.

Update Swift 3

Drag this code and drop it in the code snippet library area.

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(<#delayInSeconds#>)) {
    <#code to be executed after a specified delay#>
}
查看更多
怪性笑人.
5楼-- · 2019-01-01 03:07

Here's the Swift 3 way to queue work after a delay.

DispatchQueue.main.asyncAfter(
  DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
    // do work
}
查看更多
墨雨无痕
6楼-- · 2019-01-01 03:10

Here is how you can trigger a block after a delay in 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)
}

Its included as a standard function in my repo.

查看更多
荒废的爱情
7楼-- · 2019-01-01 03:13

There's a nice one in the BlocksKit framework.

BlocksKit

(and the class)

BBlocksKit.m

查看更多
登录 后发表回答