When I use
timer = NSTimer.scheduledTimerWithTimeInterval(0.75, target: self, selector: Selector("drawInTime"), userInfo: nil, repeats: false)
it works fine but if I want to use a variable (instead of 0.75) for the timeInterval parameter
var waitTime = CGFloat(numberOMiliseconds) / 1000.0
timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval: waitTime, target: self, selector: Selector("drawInTime"), userInfo: nil, repeats: false)
or
timer = NSTimer.scheduledTimerWithTimeInterval(waitTime, target: self, selector: Selector("drawInTime"), userInfo: nil, repeats: false)
then I get the following error "Swift compiler error: Extra argument 'selector' in call".
Can somebody help please?
If you look at the scheduledTimerWithTimeInterval signature:
class func scheduledTimerWithTimeInterval(ti: NSTimeInterval, target aTarget: AnyObject, selector aSelector: Selector, userInfo: AnyObject?, repeats yesOrNo: Bool) -> NSTimer
you notice that the method doesn't have an external name for the first parameter (that's default for methods), so you don't have to use the timeInterval external name.
Moreover, its expected type is NSTimeInterval, which is a typealias for Double, but you are passing a CGFloat.
So you should change your code to:
var waitTime = Double(numberOMiliseconds) / 1000.0
timer = NSTimer.scheduledTimerWithTimeInterval(waitTime, target: self, selector: Selector("drawInTime"), userInfo: nil, repeats: false)
Related
My last bug before uploading (Fingers Crossed). I am using a NSTimer and then invalidate it when I have paused the game. However, when it resumes it gives a larger gap. If I comment out the invalidate and just use the scene!.view!.paused = true code then gives me a shorter gap.
I may be able to do it differently but I want to try and find the solution for this. I have learn this way and am comfortable with it.
if touch.name == "pause" {
pause.hidden = true
play.hidden = false
timer.invalidate()
scoreTimer.invalidate()
scene!.view!.paused = true
}
if touch.name == "play" {
pause.hidden = false
play.hidden = true
scene!.view!.paused = false
scoreTimer = NSTimer.scheduledTimerWithTimeInterval(1.1, target:
self, selector: #selector(GameScene.updatescore), userInfo: nil, repeats: true)
timer = NSTimer.scheduledTimerWithTimeInterval(2.5, target:
self, selector: #selector(GameScene.makeTraffic), userInfo: nil, repeats: true)
}
After updating to Swift 2.2 and Xcode 7.3, my repeating NSTimer has stopped repeating.
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(rotate), userInfo: nil, repeats: true)
timer.fire()
Selector fires once, then won't fire again until after window closes or is minimized.
Anyone else? Any suggestions?
Timers need to be always scheduled or invalidated in the same thread, may be you're calling it inside an async block? Try schedule it in the main queue:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(rotate), userInfo: nil, repeats: true)
timer.fire()
})
func startTimer() {
let timer = NSTimer(timeInterval: 1, target: self, selector: #selector(MainViewController.updateLabel), userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
}
This works for me in Swift 2.2
Apples documentation doesn't say anything about dispatch_async. Is there any reason to use it...just curious...still learning
Use the timerWithTimeInterval:invocation:repeats: or timerWithTimeInterval:target:selector:userInfo:repeats: class method to create the timer object without scheduling it on a run loop. (After creating it, you must add the timer to a run loop manually by calling the addTimer:forMode: method of the corresponding NSRunLoop object.)
dispatch_async(dispatch_get_main_queue()) {
self.timer = NSTimer(timeInterval:1.0, target:self, selector: #selector(self.rotate), userInfo:nil, repeats:true)
NSRunLoop.currentRunLoop().addTimer(self.timer!, forMode: NSRunLoopCommonModes)
}
It's a threading issue as well as either not properly being added or processing within NSRunLoop automatically. Manually doing this on the same thread fixed it.
Thanks everyone for help and recommendations.
I have a tab bar application and i have a button on my first view which i want to when pressed switch to my second tab programmatically in the tab bar.
I can't quite seem to figure it out how to get the index etc to switch to it i've tried stuff like this.
tababarController.selectedIndex = 1
With no success.
Thats pretty simple tabBarController is declared as an optional type
var tabBarController: UITabBarController? { get }
The nearest ancestor in the view controller hierarchy that is a tab bar
controller. If the view controller or one of its ancestors is a child
of a tab bar controller, this property contains the owning tab bar
controller. This property is nil if the view controller is not
embedded inside a tab bar controller.
So you just need to add "?" at the end of it:
#IBAction func goToSecond(_ sender: Any) {
tabBarController?.selectedIndex = 1
}
Swift 3:
func switchToDataTab() {
Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(switchToDataTabCont), userInfo: nil, repeats: false)
}
func switchToDataTabCont(){
tabBarController!.selectedIndex = 0
}
Swift 4+:
func switchToDataTab() {
Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(switchToDataTabCont), userInfo: nil, repeats: false)
}
#objc func switchToDataTabCont(){
tabBarController!.selectedIndex = 0
}
The solution provided by Leo Dabus (see above) works fine for me. However - some controls have bad states. Can't fix that, but this little workaround will do you all good:
func switchToDataTab(){
NSTimer.scheduledTimerWithTimeInterval(0.2,
target: self,
selector: "switchToDataTabCont",
userInfo: nil,
repeats: false)
}
func switchToDataTabCont(){
tabBarController!.selectedIndex = 0
}
Add to Anthony's code:
func switchToDataTab(){
NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: #selector(switchToDataTabCont), userInfo: nil,repeats: false)
}
func switchToDataTabCont(){
tabBarController!.selectedIndex = 0
}
Where the selector class has been changed to
#selector(switchToDataTabCont)
I'm trying to create a simple animation in watch kit and i don't find the helpful "completion" that allows to perform a method at the end of the animation.
In the code the updateLabel is executed at the same time of the animation.
Here is the code:
var timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: Selector("someSelector"), userInfo: nil, repeats: false)
func testSequence() {
arcImage.setImageNamed("test")
arcImage.startAnimatingWithImagesInRange(NSMakeRange(1, 30), duration: 3, repeatCount: 1)
updateLabel()
}
func updateLabel() {
label.setText("update")
}
Knowing the duration of the animation, could use a NSTimer to call a method after the duration of the animation is completed.
var nsTimerObject:NSTimer = NSTimer.scheduledTimerWithTimeInterval(timeInSeconds, target: self, selector: "methodToBeCalled", userInfo: nil, repeats: false)
Just a simple task, but I'm in trouble. Trying to make a different way but it fails.
How to init NSTimer with declared previously variable? Neither var nor let helps.
The initial value of a property (in your case: timer) cannot depend on another property of the class (in your case: interval).
Therefore you have to move the assigment timer = NSTimer(interval, ...) into a method of the
class, e.g. into viewDidLoad. As a consequence, timer has to be defined as an
optional or implicitly unwrapped optional.
Note also that Selector(...) takes a literal string as argument, not the method itself.
So this should work:
class ViewController: UIViewController {
var interval : NSTimeInterval = 1.0
var timer : NSTimer!
func timerRedraw() {
}
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer(timeInterval: interval, target: self, selector: Selector("timerRedraw"), userInfo: nil, repeats: true)
// ...
}
// Other methods ...
}
Try:
var interval:NSTimeInterval = 1.0
var timer = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: "timerRedraw:", userInfo: nil, repeats: true)
pro-tip and hopefully an appreciated FYI: Swift functions should also start with lower case letters (i.e. "timerRedraw").