是否有一种方法可以在延迟后用一个基本参数调用块,就像使用performSelector:withObject:afterDelay:但是使用int/double/float这样的参数?
当前回答
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")
})
在swift 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: {
})
其他回答
于2021年4月更新,使用Xcode 12.4。这仍然有效,除了现在+按钮显示更多的图标,包括视图库和Modifiers库(见下文),并且视图可能是默认的。 所以一定要选择Snippets库,如下图所示。
(2020年6月在Xcode 11.3.1上验证)
Xcode提供了一个代码片段来做到这一点。您只需输入延迟值和希望在延迟后运行的代码。
点击Xcode右上方的+按钮,当你在编辑一些代码时(而不是在Project Navigator中,在那里会显示其他库,如Capabilities) 确保Snippets库(参见截图,带有{}的图标)被选中,从可用的图标中退出。 搜索之后 它将只返回一个搜索结果,这是所需的片段(见截图)。双击它,你就可以开始了。
我相信作者不是在问如何等待一个分数时间(延迟),而是如何传递一个标量作为参数的选择器(withObject:)和现代objective C中最快的方法是:
[obj performSelector:... withObject:@(0.123123123) afterDelay:10]
你的选择器必须改变它的参数为NSNumber,并使用floatValue或doubleValue这样的选择器检索值
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
}
如果你喜欢一个框架,也有一些更方便的功能,然后签出handysswift。你可以通过Carthage将它添加到你的项目中,然后像上面的例子一样使用它:
import HandySwift
delay(bySeconds: 1.5) {
// delayed code
}
按Cmd + Shift + L显示Xcode内置代码片段库:
寻找分派之后,然后,只需拖放到您的代码。
推荐文章
- CFNetwork SSLHandshake iOS 9失败
- 请求失败:不可接受的内容类型:文本/html使用AFNetworking 2.0
- 缺少推荐的图标文件-该包不包含iPhone / iPod Touch的应用程序图标,像素为“120x120”,png格式
- 以编程方式创建segue
- 在Objective-C中@synchronized如何锁定/解锁?
- Xcode构建失败“架构x86_64未定义的符号”
- 如何使用Xcode创建。ipa文件?
- 动态改变UILabel的字体大小
- registerForRemoteNotificationTypes: iOS 8.0及以上版本不支持
- 新的自动引用计数机制是如何工作的?
- 如何测试对象在Objective-C中的类?
- 在iPhone上确定用户是否启用了推送通知
- 是否有可能禁用浮动头在UITableView与UITableViewStylePlain?
- 从Cocoa应用程序执行一个终端命令
- 错误ITMS-9000:“冗余二进制文件上传。火车1.0版本已经有一个二进制版本上传。