web-dev-qa-db-ja.com

Timer.scheduledTimerはSwift 3で動作しません

1.1秒ごとにfunc adjustmentBestSongBpmHeartRate()メソッドを呼び出したいです。タイマーを使用しましたが、機能しません。私はドキュメントを読んで、多くのサンプルコードを見つけましたが、それはまだ動作します!見逃したものはありますか?

 timer = Timer.scheduledTimer(timeInterval: 1.1, target: self, selector: #selector(self.adjustmentBestSongBpmHeartRate), userInfo: nil, repeats: false)
 timer.fire()

 func adjustmentBestSongBpmHeartRate() {
    print("frr")
 }
14
Jing Bian

セレクタを使用するタイマーメソッドには、1つのパラメーターがあります。タイマー自体です。したがって、コードは次のようになります。 1

Timer.scheduledTimer(timeInterval: 1.1, 
    target: self, 
    selector: #selector(self.adjustmentBestSongBpmHeartRate(_:), 
    userInfo: nil, 
    repeats: false)

@objc func adjustmentBestSongBpmHeartRate(_ timer: Timer) {
    print("frr")
 }

アプリがiOS> = 10でのみ実行される場合、ターゲット/セレクターではなくブロックを呼び出す新しいメソッドを使用できます。よりクリーンでタイプセーフになりました:

class func scheduledTimer(withTimeInterval interval: TimeInterval, 
    repeats: Bool, 
    block: @escaping (Timer) -> Void) -> Timer

そのコードは次のようになります。

 timer = Timer.scheduledTimer(withTimeInterval: 1.1, 
        repeats: false) {
    timer in
    //Put the code that be called by the timer here.
    print("frr")
    }

タイマーブロック/クロージャーがクラスのインスタンス変数にアクセスする必要がある場合は、selfに特に注意する必要があることに注意してください。そのようなコードに適したパターンを次に示します。

 timer = Timer.scheduledTimer(withTimeInterval: 1.1, 
        repeats: false) {

    //"[weak self]" creates a "capture group" for timer
    [weak self] timer in

    //Add a guard statement to bail out of the timer code 
    //if the object has been freed.
    guard let strongSelf = self else {
        return
    }
    //Put the code that be called by the timer here.
    print(strongSelf.someProperty)
    strongSelf.someOtherProperty = someValue
    }

編集:

1:セレクタで使用するメソッドは、Objective-Cの動的ディスパッチを使用する必要があることを追加する必要があります。 @objc修飾子でメソッドを宣言したり、@objc修飾子でセレクターを定義するクラス全体を宣言したり、セレクターを定義するクラスをNSObjectまたは任意のクラスのサブクラスにしたりできます。 NSOBjectから継承します。 (タイマーがUIViewControllerのサブクラスであるNSObject内で呼び出すメソッドを定義することは非常に一般的です。

[〜#〜] edit [〜#〜]

In Swift Objective-Cから呼び出す必要のある4つのメソッドは、@objc修飾子で個別にタグ付けする必要があります。「正常に動作する」コメントはもはや正しくありません。

20
Duncan C

OperationQueue操作でタイマーを作成しても機能しないことがわかりました。これはランループがないためだと思います。

したがって、次のコードで問題が解決しました。

   DispatchQueue.main.async {
            // timer needs a runloop?
            self.timeoutTimer = Timer.scheduledTimer(timeInterval: self.timeout, target: self, selector: #selector(self.onTimeout(_:)), userInfo: nil, repeats: false)
}
20
Nick H247

Swift

私の場合、メソッドに@ obj prefix

Class TestClass {
   private var timer: Timer?

   func start() {
        guard timer == nil else { return }
        timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(handleMyFunction), userInfo: nil, repeats: false)
    }

    func stop() {
        guard timer != nil else { return }
        timer?.invalidate()
        timer = nil
    }


    @objc func handleMyFunction() {
        // Code here
    }
}
10
Jorge Casariego

これを試して -

if #available(iOS 10.0, *) {
     self.timer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: { _ in
         self.update()
     })
} else {
     self.timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(self.update), userInfo: nil, repeats: false)
}

ほとんどの場合、問題はiOSバージョンのモバイルが原因であったに違いありません。

4
Nikhil Manapure

私は自分で尋ねた質問を解決しました。 Apple watchを使ってiphoneアプリを制御しています。Apple watch.

タイマーをoverride func viewDidLoad()に書き込むと、タイマーが機能しません。 Timerをoverride func viewWillAppear()に移動します。

Apple watchによる制御に何か問題があると思います


2
Jing Bian

クラスレベルでタイマーを直接初期化しようとすると、同じクラスのセレクターをターゲットにしていると機能しないことがわかりました。起動すると、セレクターが見つかりません。

これを回避するには、タイマーを初期化しますafterセレクターを含むオブジェクトが初期化されました。同じクラスにある場合は、ViewDidLoadなどに初期化コードを入れます。イニシャライザではありません。その後、動作します。ディスパッチキューは必要ありません。

また、タイマーをパラメーターとして受け入れるセレクターを使用する必要がありますnot。たくさんの票を投じた答えに反して、それは実際には真実ではありません。より具体的には、それがなくても私にとってはうまく機能します。

ちなみに、ディスパッチキューが機能した理由は、オブジェクトの初期化後にタイマーを強制的に作成し、上記のステートメントを確認しているためだと思います。

let timer:Timer?

override func viewDidLoad(){
    super.viewDidLoad()

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

    timer.fire()

}

func adjustmentBestSongBpmHeartRate() {
    print("frr")
}

注:これはメモリから入力されたコードであり、Xcodeからコピーされたものではないため、コンパイルされない場合がありますが、うまくいけばアイデアが得られます。

1
MarqueIV

Swift 5 Swift 4 Dispatch Queue Asyncを使用した簡単な方法のみの呼び出し

DispatchQueue.main.async 
{
   self.andicator.stopAnimating()
   self.bgv.isHidden = true

   Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { _ in

       obj.showAlert(title: "Successfully!", message: "Video save successfully to Library directory.", viewController: self)

   })
}
1
Shakeel Ahmed

私の2セント。 「didLoad」について、およびそれを呼び出すときに読みます。遅延を使用できます:

class ViewController: UIViewController {

    var timer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        startTimer()
    }


    final func killTimer(){
        self.timer?.invalidate()
        self.timer = nil
    }


    final private func startTimer() {

        // make it re-entrant:
        // if timer is running, kill it and start from scratch
        self.killTimer()
        let fire = Date().addingTimeInterval(1)
        let deltaT : TimeInterval = 1.0

        self.timer = Timer(fire: fire, interval: deltaT, repeats: true, block: { (t: Timer) in

            print("hello")

        })

    RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)

    }
0
ingconti

Swift

var timer = Timer()

timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.compruebaConexion), userInfo: nil, repeats: true)
0
user3711263