Swift-NSTimer & setNeedDisplay - ios

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(setNeedsDisplay) userInfo:self repeats:YES];
I want know how to write the code above in swift.thank u.

Sample usage NSTimer's timer schedule event -
// create a timer instance
let timer = NSTimer(timeInterval: 1.0, target: self, selector: "timerEventTriggered:", userInfo: nil, repeats: true)
// adding timer to current run loop
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
// implement the event which is triggered by scheduled timer
func timerEventTriggered(timer:NSTimer!) {
...
}
Note : This was just the sample usage, you can change the variable and method names as per your context.

var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("yourFunction"), userInfo: nil, repeats: true)
func yourFunction() {
// Do something
}
/////other way.......
dispatch_after(timer, dispatch_get_main_queue()) { () -> Void in
//do same like in yourFunction()
}
}

The code can be written as
Swift 2
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("setNeedsDisplay"), userInfo: self, repeats: true)
func setNeedsDisplay() {
}
Swift 3, 4, 5
var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.setNeedsDisplay), userInfo: self, repeats: true)
#objc func setNeedsDisplay() {
}

var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.setNeedsDisplay), userInfo: self, repeats: true)

Related

Swift 5 - How to make timer work in background

I am just using NotifcationObserver in viewDidLoad
NotificationCenter.default.addObserver(self, selector: #selector(backgroundRefreshStatusDidChange), name: UIApplication.didEnterBackgroundNotification, object: nil)
and using timer like this
#objc func backgroundRefreshStatusDidChange(notification: NSNotification) { print("New status: (UIApplication.shared.backgroundRefreshStatus)") timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true) }
When app goes into the background mode, the Timer is Stoped but I want timer to running if app is background mode.
You need to start timer on global Dispatch Queue like so:
#objc func backgroundRefreshStatusDidChange(notification: NSNotification) {
print("New status: (UIApplication.shared.backgroundRefreshStatus)")
DispatchQueue.global().async {
self.timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
}

Getting : "Attempt to dismiss from view controller while a presentation or dismiss is in progress"

A Swift 4 quiz app.
First view - select num of questions to solve. (use segue to second view)
Second view - start quiz ->checked answer and send "correct" or "wrong" msg to third view. (use segue way to third view)
When the third view appears I get the error:
Attempt to dismiss from view controller <XXX.StartQuizViewController: 0x7fc893f09770> while a presentation or dismiss is in progress!
I've tried using:
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute:....
The warning message goes away but the problem is that I have no access to all the variables that I obtained from the second view for use in the third view.
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
if self.answerStatus == "Correct!" {
self.correctWrongStatusLabel.text = self.answerStatus
self.praiseLabel.text = "Good job!"
self.correctAnswerIsLabel.text = ""
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: false)
self.fireTimer()
} else if self.answerStatus == "Wrong!" {
self.correctWrongStatusLabel.text = self.answerStatus
self.praiseLabel.text = "Maybe next time!"
self.correctAnswerIsLabel.text = "回答 : \(self.correctAnswerIs)"
let timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: false)
self.fireTimer()
}
})
#objc func fireTimer() {
delegate?.answerStatusReceived(answerStatusString: answerStatusString)
self.dismiss(animated: true, completion: nil)
}
After the second view appear with the quiz, when the user select an answer, it will checked it against the correct answer and display a response saying the answer is correct or wrong. the response view must automatically closes after displaying for XX seconds.
I think you can't dismiss VC while in load, even if you add delay but no guarantee. Try add timer in viewDidAppear. Also, your self.fireTimer() doesn't necessary.
override func viewDidLoad() {
super.viewDidLoad()
if self.answerStatus == "Correct!" {
self.correctWrongStatusLabel.text = self.answerStatus
self.praiseLabel.text = "Good job!"
self.correctAnswerIsLabel.text = ""
} else if self.answerStatus == "Wrong!" {
self.correctWrongStatusLabel.text = self.answerStatus
self.praiseLabel.text = "Maybe next time!"
self.correctAnswerIsLabel.text = "回答 : \(self.correctAnswerIs)"
}
}
override func viewDidAppear() {
super.viewDidAppear()
if self.answerStatus == "Correct!" {
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: false)
} else if self.answerStatus == "Wrong!" {
let timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: false)
}
}
#objc func fireTimer() {
delegate?.answerStatusReceived(answerStatusString: answerStatusString)
self.dismiss(animated: true, completion: nil)
}
Have you tried removing the DispatchQueue method?
I would do it like this:
override func viewDidLoad() {
super.viewDidLoad()
if self.answerStatus == "Correct!" {
self.correctWrongStatusLabel.text = self.answerStatus
self.praiseLabel.text = "Good job!"
self.correctAnswerIsLabel.text = ""
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: false)
self.fireTimer()
} else if self.answerStatus == "Wrong!" {
self.correctWrongStatusLabel.text = self.answerStatus
self.praiseLabel.text = "Maybe next time!"
self.correctAnswerIsLabel.text = "回答 : \(self.correctAnswerIs)"
let timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: false)
self.fireTimer()
}
}
#objc func fireTimer() {
delegate?.answerStatusReceived(answerStatusString: answerStatusString)
dismiss(animated: true, completion: nil)
}
I think you included the function FireTimer() inside the viewDidLoad method, so I would add a bracket "}" in the line before the function.
Let me know if it works! :)
simply use:-- dismiss(animated: true, completion: nil) and omit self

Programmed segues will not work properly

I am running a program in xCode 7 and I would like to perform a segue based on the value of a certain string. Here is my viewDidLoad() code:
override func viewDidLoad() {
super.viewDidLoad()
initialGreeting()
NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: #selector(ViewController.updateTime), userInfo: nil, repeats: true)
NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: #selector(ViewController.updateGreeting), userInfo: nil, repeats: true)
if(name == ""){
self.performSegueWithIdentifier("segue", sender: nil)
}
}
What matters in the code:
if(name == ""){
self.performSegueWithIdentifier("segue", sender: nil)
}
I know this code is running because I had previously inserted a print statement which worked. What I don't understand is why the self.performSegueWithIndentifier isn't working? Somebody please explain this problem.

How to pause and restart NSTimer.scheduledTimerWithTimeInterval in spritekit [SWIFT] when home button is pressed?

I'm new to swift & spritekit and wanted to know how is it possible to detect if the home button is pressed ?
The main problem is that I have NSTimer.scheduledTimerWithTimeInterval running to generate multiple characters in didMoveToView, and everything is going well, but when I pause the game with home button and restart the game a few seconds later, the characters floods out alot. I assume that the NSTimer had not been paused , therefore, flooding alot of characters when relaunching the app. I would want to know a simple solution and example, how will I pause when home button is pressed, and resuming when the app relaunches ? I would love to here from you!
testEnemy = NSTimer.scheduledTimerWithTimeInterval(1.2,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
///This is the part of the project code for generating the characters within the didMoveToView
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("appEnterIntoBackGround:"), name:UIApplicationDidEnterBackgroundNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("appBecomeActive:"), name:UIApplicationWillEnterForegroundNotification, object: nil)
//start the timer and calls the timerUpdate method every 1.0 seconds
myTimer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
if(skview.level == 3) {
myTimer2 = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
}
testEnemy = NSTimer.scheduledTimerWithTimeInterval(1.2,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
}
func appEnterIntoBackGround(notification : NSNotification) {
let skview = self.view as! GameSKView!
print("App is in Background")
testEnemy.invalidate() //remove timer here when add enter into background.
if(skview.level == 3) {
myTimer2.invalidate()
}
myTimer.invalidate()
}
func appBecomeActive(notification : NSNotification) {
let skview = self.view as! GameSKView!
// print("App is active now")
//add your timer again when app enter into foreground
testEnemy = NSTimer.scheduledTimerWithTimeInterval(1.2,target: self,selector: "timerUpdate",userInfo: nil,repeats: true)
if(skview.level == 3) {
myTimer2 = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
}
testEnemy = NSTimer.scheduledTimerWithTimeInterval(1.2,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
}
You can use NSNotificationCenter for that will fire a notification when you app enter into background or foreground as shown into below code:
var testEnemy : NSTimer?
override func didMoveToView(view: SKView) {
/* Setup your scene here */
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("appEnterIntoBackGround:"), name:UIApplicationDidEnterBackgroundNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("appBecomeActive:"), name:UIApplicationWillEnterForegroundNotification, object: nil)
testEnemy = NSTimer.scheduledTimerWithTimeInterval(1.2,
target: self,
selector: "timerUpdate",
userInfo: nil,
repeats: true)
}
And below is the helper methods:
func timerUpdate() {
print("called")
}
func appEnterIntoBackGround(notification : NSNotification) {
print("App is in Background")
testEnemy!.invalidate() //remove timer here when add enter into background.
}
func appBecomeActive(notification : NSNotification) {
print("App is active now")
//add your timer again when app enter into foreground
testEnemy = NSTimer.scheduledTimerWithTimeInterval(1.2,target: self,selector: "timerUpdate",userInfo: nil,repeats: true)
}

Does not animate on pressing animate button

Have an animation project which does not animate when I press the button. What am I doing wrong. Here is the code in the view controller:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var startStopAnimating: UIButton!
#IBOutlet weak var imageView: UIImageView!
// image arrays
let frames: [String] = ["frame1.png", "frame2.png", "frame3.png", "frame4.png", "frame5.png", "frame6.png", "frame7.png"]
let swan: [String] = ["swanFrame1", "swanFrame2", "swanFrame3"]
let swirl: [String] = ["swirlFrame1", "swirlFrame2", "swirlFrame3"]
let starryNight: [String] = ["starryNight1", "starryNight2", "starryNight3"]
let doveWithBranch: [String] = ["doveWithBranch1", "doveWithBranch2", "doveWithBranch3"]
let tanCandles: [String] = ["tanCandles1", "tanCandles2", "tanCandles3", "tanCandles4"]
let buddhaFloat: [String] = ["buddhaFloat1", "buddhaFloat2", "buddhaFloat3", "buddhaFloat4", "buddhaFloat5", "buddhaFloat6"]
// timer vars
var timer = NSTimer()
var isAnimating = true
var counter = 1
var arrayIndex = 0
var pauseCheck = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
randomizedFuncs()
}
#IBAction func startStopAnimateButton(sender: AnyObject) {
if isAnimating == true {
timer.invalidate()
startStopAnimating.setTitle("Animate", forState: UIControlState.Normal)
} else {
startStopAnimating.setTitle("Stop Animating", forState: UIControlState.Normal)
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "pauseCheck", userInfo: nil, repeats: true)
}
}
func framesFunc() {
if arrayIndex == swan.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 1
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "swanFunc", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
func swanFunc() {
if arrayIndex == frames.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 2
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "swirlFunc", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
func swirlFunc() {
if arrayIndex == swirl.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 3
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "starryNightFunc", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
func starryNightFunc() {
if arrayIndex == starryNight.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 4
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "doveWithBranchFunc", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
func doveWithBranchFunc() {
if arrayIndex == doveWithBranch.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 5
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "tanCandlesFunc", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
func tanCandlesFunc() {
if arrayIndex == tanCandles.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 6
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "buddhaFloatFunc", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
func buddhaFloatFunc() {
if arrayIndex == buddhaFloat.count-1 {
arrayIndex = 0
} else {
arrayIndex++
}
imageView.image = UIImage(named: frames[arrayIndex])
counter++
pauseCheck = 7
if counter == 50 {
arrayIndex = 0
timer.invalidate()
isAnimating = false
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "frames Func", userInfo: nil, repeats: true)
isAnimating = true
counter = 0
arrayIndex = 0
}
}
// pauses the images and restarts them where they left off, its called in the start/stop action
func pauseCheckFunc() {
if pauseCheck == 1 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "framesFunc", userInfo: nil, repeats: true)
} else if pauseCheck == 2 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "swanFunc", userInfo: nil, repeats: true)
} else if pauseCheck == 3 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "swirlFunc", userInfo: nil, repeats: true)
} else if pauseCheck == 4 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "starryNightFunc", userInfo: nil, repeats: true)
} else if pauseCheck == 5 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "doveWithBranchFunc", userInfo: nil, repeats: true)
} else if pauseCheck == 6 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "tanCandlesFunc", userInfo: nil, repeats: true)
} else if pauseCheck == 7 {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "buddhaFloatFunc", userInfo: nil, repeats: true)
}
}
func randomizedFuncs() {
let randomNumber = Int(arc4random_uniform(UInt32(7)))
if randomNumber == 0 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "swanFunc", userInfo: "nil", repeats: true)
} else if randomNumber == 1 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "framesFunc", userInfo: "nil", repeats: true)
} else if randomNumber == 2 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "swirlFunc", userInfo: "nil", repeats: true)
} else if randomNumber == 3 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "starryNightFunc", userInfo: "nil", repeats: true)
} else if randomNumber == 4 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "doveWithBranchFunc", userInfo: "nil", repeats: true)
} else if randomNumber == 5 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "tanCandlesFunc", userInfo: "nil", repeats: true)
} else if randomNumber == 6 {
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "buddhaFloatFunc", userInfo: "nil", repeats: true)
}
}
}
You're using pauseCheck as a selector but that's not a function in your code. I think you meant pauseCheckFunc?
Also I don't see anywhere in your code a command to actually start animating. You also don't properly set animation frames on your UIImages. It's unclear why you're using timers to animate images. You can just set an array of images to the animationImages property of your UIImages, and just use startAnimating() and stopAnimating() to start and stop animation.

Resources