Сделайте что-нибудь каждые x минут в Swift

Как я могу запускать функцию каждую минуту? В JavaScript я могу сделать что-то вроде setInterval, что-то подобное существует в Swift?

Требуемый вывод:

Привет мир раз в минуту...

Ответ 1

var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)

func sayHello() 
{
    NSLog("hello World")
}

Не забудьте импортировать Foundation.

Swift 4:

 var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)

 @objc func sayHello() 
 {
     NSLog("hello World")
 }

Ответ 2

В Swift 3 вы можете создать Timer. И, если вы используете таргетинг на iOS версии 10 и выше, вы можете использовать разметку на основе блоков, что упрощает потенциальные сильные ссылочные циклы, например:

weak var timer: Timer?

func startTimer() {
    timer?.invalidate()   // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
    timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
        // do something here
    }
}

func stopTimer() {
    timer?.invalidate()
}

// if appropriate, make sure to stop your timer in `deinit`

deinit {
    stopTimer()
}

В Swift 2 вы создаете NSTimer. И если вы используете Swift 2, вы можете использовать версию iOS до 10.0, и в этом случае вам придется использовать более старый шаблон target/selector:

weak var timer: NSTimer?

func startTimer() {
    timer?.invalidate()   // just in case you had existing `NSTimer`, `invalidate` it before we lose our reference to it
    timer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true)
}

func handleTimer(timer: NSTimer) {
    // do something here
}

func stopTimer() {
    timer?.invalidate()
}

// because this old target/selector approach will keep a strong reference
// to the `target`, if you want the timer to stop when the view controller
// is dismissed, you can't stop the timer in `deinit`, but rather have to 
// detect the dismissing of the view controller using other mechanisms. Commonly,
// we used to detect the view disappearing, like below:

override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    stopTimer()
}

Хотя NSTimer, как правило, лучше всего, для полноты, я должен отметить, что вы также можете использовать таймер отправки, который полезен для планирования таймеров по фоновым потокам. При отправке таймеров, так как они на основе блоков, это позволяет избежать некоторых сильных проблем опорного цикла со старым target/<Т24 > модель NSTimer, до тех пор, пока вы используете weak ссылки.Р >

Итак, в Swift 3:

var timer: DispatchSourceTimer?

func startTimer() {
    let queue = DispatchQueue(label: "com.domain.app.timer")  // you can also use `DispatchQueue.main`, if you want
    timer = DispatchSource.makeTimerSource(queue: queue)
    timer!.scheduleRepeating(deadline: .now(), interval: .seconds(60))
    timer!.setEventHandler { [weak self] in
        // do whatever you want here
    }
    timer!.resume()
}

func stopTimer() {
    timer?.cancel()
    timer = nil
}

deinit {
    self.stopTimer()
}

В Swift 2:

var timer: dispatch_source_t?

func startTimer() {
    let queue = dispatch_queue_create("com.domain.app.timer", nil) // again, you can use `dispatch_get_main_queue()` if you want to use the main queue
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
    dispatch_source_set_timer(timer!, DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC, 1 * NSEC_PER_SEC) // every 60 seconds, with leeway of 1 second
    dispatch_source_set_event_handler(timer!) { [weak self] in
        // do whatever you want here
    }
    dispatch_resume(timer!)
}

func stopTimer() {
    if let timer = timer {
        dispatch_source_cancel(timer)
        self.timer = nil
    }
}

deinit {
    self.stopTimer()
}

Дополнительные сведения см. в разделе "Создание таймера" в примерах источника отправки в разделе Отладочные файлы в руководстве по программированию Concurrency.

Ответ 3

Здесь обновление для ответа NSTimer для Swift 3 (в котором NSTimer было переименовано в Timer), используя закрытие, а не именованную функцию:

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
    (_) in
    print("Hello world")
}

Ответ 4

Вы можете использовать NSTimer

var timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)

В селекторе() вы введете имя своей функции

Ответ 5

В swift 3.0 GCD получил рефакторинг:

let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)

timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
    NSLog("Hello World")
}
timer.resume()

Это особенно полезно, когда вам нужно отправить отдельную очередь. Кроме того, если вы планируете использовать это для обновления пользовательского интерфейса, я предлагаю заглянуть в CADisplayLink, поскольку он синхронизирован с частотой обновления GPU.

Ответ 6

Если вы можете позволить себе некоторое время дрейфа здесь простое решение, выполняющее какой-то код каждую минуту:

private func executeRepeatedly() {
    // put your code here

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
        self?.executeRepeatedly()
    }
}

Просто запустите executeRepeatedly() один раз, и он будет выполняться каждую минуту. Выполнение прекращается, когда освобождается объект-владелец (self). Вы также можете использовать флаг, указывающий, что выполнение должно быть остановлено.