Использование 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)
}
}
10 ответов
Вы можете создать запланированные таймер, который автоматически добавляет себя в runloop и начинает стрелять:
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "timerDidFire:", userInfo: userInfo, repeats: true)
или вы можете сохранить свой текущий код и добавить таймер в runloop, когда будете готовы к нему:
let myTimer = NSTimer(timeInterval: 0.5, target: self, selector: "timerDidFire:", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(myTimer, forMode: NSRunLoopCommonModes)
Я использую аналогичный подход к люку. Только предостережение для людей, которые являются "частными методами" пуристов:
Не делайте обратный вызов приватным в Swift.
Если вы пишете:
private func timerCallBack(timer: NSTimer){
..
вы получите:
timerCallBack:]: непризнанной селектор послал экземпляр... Прекращения приложения из-за необработанных исключений 'NSInvalidArgumentException'
NSTimer не запланированы автоматически, если вы не используете NSTimer.scheduledTimerWithTimeInterval
:
myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc", userInfo: nil, repeats: true)
как указали Drewag и Ryan, вам нужно создать запланированный таймер (или запланировать его самостоятельно), проще всего создать его по расписанию уже с:
myTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "timerFunc:", userInfo: nil, repeats: true)
вам также нужно изменить свое определение timerFunc (и связанного селектора), чтобы принять аргумент и закончить":"
func timerFunc(timer:NSTimer!) {
...
}
Swift 3.0 синтаксис для выполнения цикла thingy:
RunLoop.current.add(myTimer, forMode: .commonModes)
Для 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)
это немного кода, который демонстрирует, как вызвать функцию (с задержкой) с параметром и без него.
используйте это в новом проекте в 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()
}
}
обратите внимание, что в любом случае вы должны реализовать отложенную функцию с параметром (timer : NSTimer), чтобы иметь возможность аннулировать (завершить, завершить) таймер. И с passend "timer" у вас также есть доступ к userInfo (и там вы можете поместить любой объект, а не только строковые объекты, а также типы коллекций, такие как массивы и словари).
оригинальные документы Apple говорят "" - > таймер передает себя в качестве аргумента, таким образом, метод примет следующий шаблон: - (void)timerFireMethod: (NSTimer *)таймер Читайте полностью -> здесь
scheduledTimerWithTimeInterval ставил таймер на другой RunLoop во время запуска приложения. Если я просто инициализирую таймер, а затем использую NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)
вместо этого, он отлично работает.
С 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
}
чтобы сделать это с помощью метода, предложенного OP, вам нужно добавить его в цикл выполнения:
myTimer = NSTimer(timeInterval: 5.0, target: self, selector:"timerFunc", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(myTimer, forMode:NSDefaultRunLoopMode)
в документации также говорится, что цель должна принять аргумент, но она работает без него.
func timerFireMethod(timer: NSTimer) { }