是否有一种方法可以在延迟后用一个基本参数调用块,就像使用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];

其他回答

Xcode 10.2和Swift 5及以上

DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
   // code to execute                 
})

ObjC版本

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    //code to execute
});

以下是在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)
}

它包括作为一个标准函数在我的回购。

按Cmd + Shift + L显示Xcode内置代码片段库:

寻找分派之后,然后,只需拖放到您的代码。

PerformSelector:WithObject总是接受一个对象,因此为了传递诸如int/double/float等参数.....你可以用这样的东西。

//NSNumber是一个对象

[self performSelector:@selector(setUserAlphaNumber:)
     withObject: [NSNumber numberWithFloat: 1.0f]       
     afterDelay:1.5];



-(void) setUserAlphaNumber: (NSNumber*) number{

     [txtUsername setAlpha: [number floatValue] ];

}

同样的方式,你可以使用[NSNumber numberWithInt:]等....在接收方法中,您可以将数字转换为[数字int]或[数字double]的格式。

这里有一个方便的帮手来防止烦人的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
}

如果你喜欢一个框架,也有一些更方便的功能,然后签出handysswift。你可以通过Carthage将它添加到你的项目中,然后像上面的例子一样使用它:

import HandySwift    

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