有没有一种方法可以在延迟后使用一个原始参数调用块,就像使用
performSelector:withObject:afterDelay:
一样,但参数是像 int
/double
/float
这样的类型?performSelector:withObject:afterDelay:
一样,但参数是像 int
/double
/float
这样的类型?这里有一个方便的助手,可以避免反复进行烦人的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
}
import HandySwift
delay(bySeconds: 1.5) {
// delayed code
}
这是Swift 3中延迟后排队工作的方法。
DispatchQueue.main.asyncAfter(
DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
// do work
}
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
// Trigger the function/action after the delay of 1Sec
}
+
按钮会呈现更多图标,包括Views库和Modifiers库(见下文),并且Views可能是默认选项。
所以请确保选择Snippets库,如下图所示。
(2020年6月在Xcode 11.3.1上验证)
Xcode提供了一个代码片段来实现此操作。您只需输入延迟值和延迟后要运行的代码即可。
+
按钮(而不是例如项目导航器中呈现的其他库,如Capabilities)after
你可以将参数包装在自己的类中,或者将方法调用包装在不需要传递原始类型的方法中。然后在延迟之后调用该方法,在该方法内执行您希望执行的选择器。
以下是如何在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 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 :)
}
}
}
我相信作者不是在询问如何等待一段时间(延迟),而是如何将标量作为选择器(withObject:)的参数传递,而现代Objective-C中最快的方法是:
[obj performSelector:... withObject:@(0.123123123) afterDelay:10]
你的选择器必须将其参数更改为NSNumber,并使用类似floatValue或doubleValue的选择器检索值