Использование NSTimer в Swift
В этом случае функция timerFunc() никогда не вызывается. Что мне не хватает?
class AppDelegate: NSObject, NSApplicationDelegate {
var myTimer: NSTimer? = nil
func timerFunc() {
println("timerFunc()")
}
func applicationDidFinishLaunching(aNotification: NSNotification?) {
myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
}
}
Ответы
Ответ 1
Вы можете создать запланированный таймер, который автоматически добавляется в цикл запуска и запускает:
Swift 2
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "timerDidFire:", userInfo: userInfo, repeats: true)
Свифт 3, 4, 5
Timer.scheduledTimer(withTimeInterval: 0.5, target: self, selector: #selector(timerDidFire(_:)), userInfo: userInfo, repeats: true)
Или вы можете сохранить текущий код и добавить таймер в цикл запуска, когда будете к этому готовы:
Swift 2
let myTimer = NSTimer(timeInterval: 0.5, target: self, selector: "timerDidFire:", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(myTimer, forMode: NSRunLoopCommonModes)
Свифт 3, 4, 5
let myTimer = Timer(timeInterval: 0.5, target: self, selector: #selector(timerDidFire(_:)), userInfo: nil, repeats: true)
RunLoop.current.add(myTimer, forMode: RunLoop.Mode.common)
Ответ 2
Я использую подобный подход к Люку.
Только оговорка для людей, которые являются "частными методами" пуристов:
НЕ ВКЛЮЧАЙТЕ функцию обратного вызова в Swift.
Если вы пишете:
private func timerCallBack(timer: NSTimer){
..
вы получите:
timerCallBack:]: непризнанный селектор, отправленный в экземпляр... Завершение приложения из-за неперехваченного исключения "NSInvalidArgumentException"
Ответ 3
NSTimer не назначается автоматически, если вы не используете NSTimer.scheduledTimerWithTimeInterval
:
myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc", userInfo: nil, repeats: true)
Ответ 4
Как отметил Дрюаг и Райан, вам нужно создать запланированный таймер (или запланировать его самостоятельно). Легче всего его создать, запланировав уже:
myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc:", userInfo: nil, repeats: true)
Вам также необходимо изменить определение timerFunc (и связанного с ним селектора), чтобы принять аргумент и завершить с помощью::
func timerFunc(timer:NSTimer!) {
...
}
Ответ 5
Для Swift 3
var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(ViewController.updateTimer), userInfo: nil, repeats: true);
RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)
Ответ 6
Синтаксис Swift 3.0 для цикла выполнения:
RunLoop.current.add(myTimer, forMode: .commonModes)
Ответ 7
Это немного кода, который демонстрирует, как вызывать функцию (с задержкой) с И без параметра.
Используйте это в новом проекте в xCode (singleViewApplication) и поместите код в стандартный viewController:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("delayedFunctionWithoutParameter:"), userInfo: nil, repeats: false)
let myParameter = "ParameterStringOrAnyOtherObject"
NSTimer.scheduledTimerWithTimeInterval(4.0, target: self, selector: Selector("delayedFunctionWithParameter:"), userInfo: myParameter, repeats: false)
}
// SIMPLE TIMER - Delayed Function Call
func delayedFunctionWithoutParameter(timer : NSTimer) {
print("This is a simple function beeing called without a parameter passed")
timer.invalidate()
}
// ADVANCED TIMER - Delayed Function Call with a Parameter
func delayedFunctionWithParameter(timer : NSTimer) {
// check, wether a valid Object did come over
if let myUserInfo: AnyObject = timer.userInfo {
// alternatively, assuming it is a String for sure coming over
// if let myUserInfo: String = timer.userInfo as? String {
// assuming it is a string comming over
print("This is an advanced function beeing called with a parameter (in this case: \(myUserInfo)) passed")
}
timer.invalidate()
}
}
Обратите внимание, что в любом случае вы должны реализовать задержанную функцию с параметром (таймер: NSTimer), чтобы иметь возможность аннулировать (завершить, завершить) таймер. И с помощью "таймера" passend вы также имеете доступ к userInfo (и там вы можете поместить любой Object, а не только String-Objects, а также такие типы коллекций, как массивы и словари).
Документация Original Apples гласит: "" → Таймер передает себя в качестве аргумента, таким образом, метод примет следующий шаблон:
- (void) timerFireMethod: (NSTimer *) таймер
Читать полностью → здесь
Ответ 8
Поскольку этот поток заставил меня попытаться поставить таймер на RunLoop сам (который решил мою проблему), я также отправляю свой конкретный случай - кто знает, может быть, это помогает кому-то.
Мой таймер создается во время запуска приложения и инициализации всех объектов. Моя проблема заключалась в том, что, хотя он и планировал таймер, он все равно никогда не срабатывал. Я предполагаю, что это было так, потому что scheduledTimerWithTimeInterval
помещал таймер на другой RunLoop во время запуска приложения. Если я просто инициализирую таймер, а затем использую NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)
вместо этого, он отлично работает.
Ответ 9
С помощью swift3 вы можете запустить его с помощью
var timer: Timer?
func startTimer() {
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.loop), userInfo: nil, repeats: true)
}
}
func stopTimer() {
if timer != nil {
timer?.invalidate()
timer = nil
}
}
func loop() {
//do something
}
Ответ 10
Чтобы сделать это с помощью метода, который предлагает OP, вам нужно добавить его в цикл выполнения:
myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)
В документации также говорится, что цель должна принимать аргумент, но она работает без него.
func timerFireMethod(timer: NSTimer) { }