Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 456 Vote(s) - 3.42 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Timer.scheduledTimer does not work in Swift 3

#1
I want to call the method `func adjustmentBestSongBpmHeartRate()` every 1.1 second. I used Timer, but it doesn't work. I have read the document and found a lot of sample code, it still does work! Is there anything I missed?

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

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

#2
Timer methods with a selector are supposed to have one parameter: The timer itself. Thus your code should really look like this: <sup>1</sup>

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

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


Note that if your app only runs on iOS >= 10, you can use the new method that takes a block to invoke rather than a target/selector. Much cleaner and more type-safe:

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

That code would look like this:


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

Note that if your timer block/closure needs access to instance variables from your class you have to take special care with `self`. Here's a good pattern for that sort of code:


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
}

## Edit (updated 15 December)

<sup>1</sup>: I should add that the method you use in the selector has to use Objective-C dynamic dispatch. In Swift 4 and later, the individual methods you reference must be tagged with the `@objc` tag. In previous versions of Swift you could also declare the entire class that defines the selector with the `@objc` qualifier, or you could make the class that defined the selector a subclass of `NSObject` or any class that inherits from `NSOBject`. (It's quite common to define the method the timer calls inside a `UIViewController`, which is a subclass of `NSObject`, so it used to "just work".

Reply

#3
I found that creating the timer in an OperationQueue Operation did not work. I assume this is because there is no runloop.

Therefore, the following code fixed my problem:



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

Reply

#4
Swift 5, Swift 4 Simple way only call with 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)

})
}
Reply

#5
I found that if you try to initialize the timer directly at the class-level, it won't work if you're targeting a selector in that same class. When it fires, it can't find the selector.

To get around this, I only initialize the timer ***after*** the object containing the selector has been initialized. If it's in the same class, put the initialization code in the `ViewDidLoad` or similar. Just not in the initializer. Then it will work. No dispatch queue needed.

Also, you do *not* need to use a selector that accepts the timer as a parameter. You can, but contrary to the answer with a ton of votes, that's not actually true, or more specifically, it works fine for me without it, just as you have it without it.

By the way, I think the reason the dispatch queue worked is because you're forcing the timer to be created after the object was initializing, confirming my above statement.

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

Note: This is code typed from memory, not copied from Xcode so it may not compile, but hopefully you get the idea.
Reply

#6
Try this -


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



Mostly the problem must have been because of iOS version of mobile.
Reply

#7
my two cents.
I read about "didLoad" and when invoking it.
so we can use a delay:


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)

}


Reply

#8
**Swift3**

var timer = Timer()

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

#9
**Swift 3**

In my case it worked after I added to my method the **@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
}
}
Reply

#10
I have solved the question asked by myself.
I'm using apple watch to control my iphone app.
I try to press a button on apple watch to present a new viewcontroller on iphone.

When I write Timer in `override func viewDidLoad()`, Timer doesn't work. I move Timer to `override func viewWillAppear()` it works.

I think maybe there's something wrong with controlling by apple watch

----------
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through