Làm cách nào tôi có thể sử dụng Timer (trước đây là NSTimer) trong Swift?


257

Tôi đã thử

var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)

Nhưng, tôi có một lỗi nói

'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'

1
"Làm cách nào tôi có thể sử dụng NSTimer trong Swift?" - giống như cách bạn sử dụng nó trong Objective-C. API của nó không thay đổi.
Croissant Paramag từ 30/8/2015

Câu trả lời:


534

Điều này sẽ làm việc:

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
}

Đối với Swift 4, phương thức mà bạn muốn nhận bộ chọn phải được hiển thị với Objective-C, do đó @objcthuộc tính phải được thêm vào khai báo phương thức.


2
Tôi muốn thêm rằng lớp với các phương thức này cần phải là NSObject, nếu không, bạn sẽ gặp phải lỗi chọn không được nhận dạng
Joshua

27
Kể từ Xcode 6.1, tôi đã phải thêm "@objc" vào tiêu đề hàm như thế này: "@objc func update () {". Không có nó, ứng dụng gặp sự cố khi xảy ra hỏa hoạn đầu tiên.
kev

Bạn có thể khai báo bộ đếm thời gian Var: NSTimer! ban đầu và sử dụng nó bất cứ khi nào cần thiết!
Nigilan

1
Một phiên bản có thể hữu ích hơn của cú pháp khối: let timer = Timer.schediatedTimer (withTimeInterval: timeout, repeats: false) {_ in ("Xong.")}
Teo Sartori

Bạn không thể sử dụng 'let timer = Timer (timeInterval: 0.4, lặp lại: true) {_ in ("Xong!")}' Điều này sẽ không khởi động bộ hẹn giờ và sau đó bạn không thể bắt đầu lại. Bạn phải sử dụng Timer.schediatedTimer.
Siamaster

149

Sự kiện lặp đi lặp lại

Bạn có thể sử dụng bộ đếm thời gian để thực hiện một hành động nhiều lần, như trong ví dụ sau. Bộ đếm thời gian gọi một phương thức để cập nhật nhãn cứ sau nửa giây.

nhập mô tả hình ảnh ở đây

Đây là mã cho điều đó:

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)"
    }
}

Sự kiện bị trì hoãn

Bạn cũng có thể sử dụng bộ đếm thời gian để lên lịch một sự kiện một lần trong một thời gian trong tương lai. Sự khác biệt chính từ ví dụ trên là bạn sử dụng repeats: falsethay vì true.

timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)

Ví dụ trên gọi một phương thức có tên delayedActionhai giây sau khi bộ hẹn giờ được đặt. Nó không được lặp lại, nhưng bạn vẫn có thể gọi timer.invalidate()nếu bạn cần hủy sự kiện trước khi nó xảy ra.

Ghi chú

  • Nếu có bất kỳ cơ hội nào để bắt đầu phiên bản hẹn giờ của bạn nhiều lần, trước tiên hãy chắc chắn rằng bạn làm mất hiệu lực phiên bản hẹn giờ cũ. Nếu không, bạn mất tham chiếu đến bộ đếm thời gian và bạn không thể dừng nó nữa. (xem phần hỏi đáp này )
  • Đừng sử dụng bộ hẹn giờ khi không cần thiết. Xem phần tính giờ của Hướng dẫn sử dụng năng lượng hiệu quả cho ứng dụng iOS .

Liên quan


1
@raddevus, cảm ơn vì đã cho tôi biết. Tôi đã xóa bình luận Swift 3 cũ.
Suragch

31

Đã cập nhật lên Swift 4, tận dụng 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)
    }

}

2
Hiển thị một ví dụ hoạt động, "tùy chỉnh" và "dữ liệu" nghĩa là gì nếu chức năng đang mong đợi một NSTimerđối tượng
Carlos.V

1
Nó thật sự không thành vấn đề. Bạn có thể lưu trữ bất cứ thứ gì bạn cần vào từ điển userInfo, trong trường hợp này là cặp khóa-giá trị tùy ý.
igrac817

Điều này rất hữu ích, nhưng đã phá vỡ trong Swift 3, ví dụ hoạt động: Timer.schediatedTimer (timeInterval: 1.0, target: self, selector: #selector (event), userInfo: "Info Sent", lặp lại: true)
Bobby

28

Kể từ iOS 10, cũng có một phương thức nhà máy Timer dựa trên khối mới, sạch hơn so với sử dụng bộ chọn:

    _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
        label.isHidden = true
    }

1
Cách bạn đang làm, sẽ tốt hơn nếu chỉ xóa _ = và chỉ bắt đầu với Timer?
Mật ong

2
Bạn có thể bỏ qua _ = nếu bạn tắt tiếng cảnh báo về giá trị không sử dụng hoặc nếu bạn không quan tâm đến các cảnh báo. Tôi không thích kiểm tra mã với các cảnh báo.
Josh Homann

22

Swift 3, trước 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)
      }
    }

Ghi chú

  • Nó cần phải ở trên hàng đợi chính
  • Chức năng gọi lại có thể là công khai, riêng tư, ...
  • Chức năng gọi lại cần phải được @objc

1
Tôi hiểu rằng chỉ nên gọi lại bộ đếm thời gian trên hàng đợi chính và sau đây sẽ hiệu quả hơn một chút: self.timer = Timer.schediatedTimer (withTimeInterval: 20, lặp lại: false) {bộ đếm thời gian trong DispatchQueue.main.async {print (hẹn giờ)}}
Mathieu Frenette

Đồng hồ bấm giờ của tôi không kích hoạt từ một trong các Đối tượng của tôi và điều đó đã tạo nên mánh khóe :)
Reimond Hill

@ReimondHill Bạn cần thay đổitimeInterval
onmyway133

17

Kiểm tra với:

Swift 2

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

Swift 3, 4, 5

var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)

2
Tôi đã thử nó nhưng nó nói 'Không thể tìm thấy sự quá tải cho' init 'chấp nhận các đối số được cung cấp'
user3225917

1
Tương tự ở đây, tôi đã gặp lỗi 'Không thể tìm thấy quá tải cho' init 'chấp nhận các đối số được cung cấp'. Liệu dòng này thực sự hoạt động?
Yangshun Tay

Tôi nhận được lỗi tương tự như @yangshun. Những loại đối tượng phải selflà? UIView có ổn không?
SimplGy

@SimpleAsCouldBe: vâng, điều đó ổn thôi
Midhun MP

func lượngSubmitSuccess () {self.view. SuedeToastActivity () self.view.makeToast (tin nhắn: "Số tiền đã đăng ký thành công") var timer = NSTimer.schediatedTimerWithTimeInterval (0.5, target: self, selector: "move," lặp lại: false)} func moveToBidderPage () {let loginPageView = self.storyboard? .instantiateViewContoderWithIdentifier ("pricederpageID") là! BidderPage self.navestionControll? .PushViewControll (loginPageView, hoạt hình: true)}
AG

11

Bạn sẽ cần sử dụng Timer thay vì NSTimer trong Swift 3.

Đây là một ví dụ:

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
}

11

Swift 5

Cá nhân tôi thích Timer với việc đóng khối:

    Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
       // TODO: - whatever you want
    }

Xin lưu ý, điều này chỉ có sẵn trong macOS 10.12 hoặc mới hơn. Không chắc chắn về ios.
jeff-h

Nó cũng có sẵn trong iOS.
Wissa

7

cho swift 3 và Xcode 8.2 (rất vui khi có các khối, nhưng nếu bạn biên dịch cho iOS9 VÀ muốn 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)
    }

6

Đơn giản (Swift 3.1)

Tại sao?

Đây là lớp hẹn giờ đơn giản trong swift cho phép bạn:

  • Hẹn giờ phạm vi địa phương
  • Xích
  • Một lớp lót
  • Sử dụng các cuộc gọi lại thường xuyên

Sử dụng:

SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs

Mã số:

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()
    }
}

Làm thế nào để dừng bộ hẹn giờ bên trong khối đó trong một số điều kiện?
Nhà phát triển di động iOS Android

Chỉ cần lưu trữ ref vào bộ đếm thời gian trong một lớp sau đó chỉ cần dừng cuộc gọi. Trình biên dịch xcode sẽ cho bạn biết nếu nó cần thoát, v.v.
eonist

3
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

Và tạo niềm vui bằng tên tạoEnemy

fund createEnemy ()
{
do anything ////
}

3

Đầu tiên khai báo bộ đếm thời gian của bạn

var timer: Timer?

Sau đó thêm dòng trong viewDidLoad () hoặc trong bất kỳ chức năng nào bạn muốn bắt đầu bộ hẹn giờ

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)

Đây là func bạn sẽ gọi lại để làm một cái gì đó phải là @objc

@objc func action () {
print("done")
}

2

Trong Swift 3 một cái gì đó như thế này với @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()
}

1

Nếu bạn khởi tạo phương thức hẹn giờ

let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)

func update(_ timer : Timer) {

}

sau đó thêm nó vào vòng lặp bằng phương thức bộ chọn khác sẽ không được gọi

RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)

LƯU Ý: Nếu bạn muốn điều này lặp lại, hãy lặp lại đúng và giữ tham chiếu của bộ định thời nếu không phương thức cập nhật sẽ không được gọi.

Nếu bạn đang sử dụng phương pháp này.

Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)

giữ một tài liệu tham khảo để sử dụng sau nếu lặp lại là đúng.


0

Tôi đã cố gắng thực hiện trong Lớp NSObject và điều này hiệu quả với tôi:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {  
print("Bang!") }

-2

NSTimer đã được đổi tên thành Timer trong Swift 4.2. cú pháp này sẽ hoạt động trong 4.2:

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)

Việc đổi tên đã xảy ra trong Swift 3 và các câu trả lời khác đã thực hiện cập nhật ...
Eric Aya
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.