Использование 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) { }