Как я могу использовать NSTimer в Swift?
Я старался
var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)
Но я получил сообщение об ошибке
'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
18 ответов
Это будет работать:
override func viewDidLoad() {
super.viewDidLoad()
// Swift block syntax (iOS 10+)
let timer = Timer(timeInterval: 0.4, repeats: true) { _ in print("Done!") }
// Swift >=3 selector syntax
let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
// Swift 2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
// Swift <2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}
// must be internal or public.
@objc func update() {
// Something cool
}
Для Swift 4, метод, который вы хотите получить селектор должен быть выставлен Objective-C, таким образом @objc
атрибут должен быть добавлен в объявление метода.
Вот несколько более полных примеров, обновленных для Swift 3.
Повторное событие
Вы можете использовать таймер для выполнения действия несколько раз, как показано в следующем примере. Таймер вызывает метод для обновления метки каждые полсекунды.
Вот код для этого:
import UIKit
class ViewController: UIViewController {
var counter = 0
var timer = Timer()
@IBOutlet weak var label: UILabel!
// start timer
@IBAction func startTimerButtonTapped(sender: UIButton) {
timer.invalidate() // just in case this button is tapped multiple times
// start the timer
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
// stop timer
@IBAction func cancelTimerButtonTapped(sender: UIButton) {
timer.invalidate()
}
// called every time interval from the timer
func timerAction() {
counter += 1
label.text = "\(counter)"
}
}
Задержка события
Вы также можете использовать таймер, чтобы запланировать одноразовое событие на какое-то время в будущем. Основное отличие от приведенного выше примера заключается в том, что вы используете repeats: false
вместо true
,
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
В приведенном выше примере вызывается метод с именем delayedAction
через две секунды после установки таймера. Это не повторяется, но вы все равно можете позвонить timer.invalidate()
если вам нужно отменить событие до того, как оно произойдет.
Заметки
- Если есть шанс запустить экземпляр таймера несколько раз, убедитесь, что сначала вы сделали недействительным старый экземпляр таймера. В противном случае вы потеряете ссылку на таймер и больше не сможете его остановить. (см. этот Q & A)
- Не используйте таймеры, когда они не нужны. См. Раздел таймеров в Руководстве по энергоэффективности для приложений для iOS.
связанные с
Обновлен до Swift 4, используя userInfo:
class TimerSample {
var timer: Timer?
func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(eventWith(timer:)),
userInfo: [ "foo" : "bar" ],
repeats: true)
}
// Timer expects @objc selector
@objc func eventWith(timer: Timer!) {
let info = timer.userInfo as Any
print(info)
}
}
Начиная с iOS 10, также существует новый метод фабрики Timer на основе блоков, который чище, чем использование селектора:
_ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
label.isHidden = true
}
Swift 5
Я лично предпочитаю Таймер с закрытием блока:
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
// TODO: - whatever you want
}
Swift 3, предварительно iOS 10
func schedule() {
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 20, target: self,
selector: #selector(self.timerDidFire(timer:)), userInfo: nil, repeats: false)
}
}
@objc private func timerDidFire(timer: Timer) {
print(timer)
}
Swift 3, iOS 10+
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: false) { timer in
print(timer)
}
}
Заметки
- Это должно быть в главной очереди
- Функция обратного вызова может быть общедоступной, частной, ...
- Функция обратного вызова должна быть
@objc
Проверить с:
var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true);
Вам нужно будет использовать Timer вместо NSTimer в Swift 3.
Вот пример:
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(YourController.update),
userInfo: nil,
repeats: true)
// @objc selector expected for Timer
@objc func update() {
// do what should happen when timer triggers an event
}
Сначала объявите свой таймер
var timer: Timer?
Затем добавьте строку в viewDidLoad() или в любую функцию, в которой вы хотите запустить таймер.
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)
Это функция, которую вы перезвоните, чтобы что-то сделать, это должно быть @objc
@objc func action () {
print("done")
}
Для swift 3 и Xcode 8.2 (приятно иметь блоки, но если вы компилируете для iOS9 и хотите userInfo):
...
self.timer = Timer(fireAt: fire,
interval: deltaT,
target: self,
selector: #selector(timerCallBack(timer:)),
userInfo: ["custom":"data"],
repeats: true)
RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
self.timer!.fire()
}
func timerCallBack(timer: Timer!){
let info = timer.userInfo
print(info)
}
SimpleTimer (Swift 3.1)
Зачем?
Это простой класс таймера в swift, который позволяет вам:
- Таймер с локальной областью действия
- змеевидных
- Один лайнер
- Используйте регулярные обратные вызовы
Использование:
SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs
Код:
class SimpleTimer {/*<--was named Timer, but since swift 3, NSTimer is now Timer*/
typealias Tick = ()->Void
var timer:Timer?
var interval:TimeInterval /*in seconds*/
var repeats:Bool
var tick:Tick
init( interval:TimeInterval, repeats:Bool = false, onTick:@escaping Tick){
self.interval = interval
self.repeats = repeats
self.tick = onTick
}
func start(){
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(update), userInfo: nil, repeats: true)//swift 3 upgrade
}
func stop(){
if(timer != nil){timer!.invalidate()}
}
/**
* This method must be in the public or scope
*/
@objc func update() {
tick()
}
}
Ниже приведен пример (для Swift 5.x) базового объекта Timer, созданного при нажатии кнопки UIButton. Он использует замыкание для печати текущего значения таймера в журнале и, в конечном итоге, вызывает invalidate() для остановки и удаления таймера из цикла выполнения.
@IBAction func startTimer(_ sender: UIButton) {
var runCount = 60 //for a 60 second timer
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
print(runCount)
runCount -= 1
if runCount < 0 {
timer.invalidate()
}
}
}
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
И Создай Забаву По Названию createEnemy
fund createEnemy ()
{
do anything ////
}
Я попытался сделать это в классе NSObject, и это сработало для меня:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
print("Bang!") }
В Swift 3 что-то вроде этого с @objc:
func startTimerForResendingCode() {
let timerIntervalForResendingCode = TimeInterval(60)
Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
target: self,
selector: #selector(timerEndedUp),
userInfo: nil,
repeats: false)
}
@objc func timerEndedUp() {
output?.timerHasFinishedAndCodeMayBeResended()
}
Если вы инициируете метод таймера
let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)
func update(_ timer : Timer) {
}
затем добавьте его в цикл с помощью метода, который не будет вызываться другим селектором
RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)
ПРИМЕЧАНИЕ. Если вы хотите, чтобы это повторялось, сделайте true для повторов и сохраните ссылку на таймер, иначе метод обновления не будет вызван.
Если вы используете этот метод.
Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)
сохраните ссылку для последующего использования, если повторы верны.
переопределить функцию viewDidLoad() {
super.viewDidLoad()
configUI()
}
func configUI() {
let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeat: true)
}
@objc func update () {
}
NSTimer был переименован в Timer в Swift 4.2. этот синтаксис будет работать в 4.2:
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)