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)
}
}
Related
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
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.
At the end of my game it runs a function to switch you to the finished screen.
View Controller -> Finish view controller
I want to put the admob interstitial in between.
Here was the original code
NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(1), target: self, selector: "switchScreen", userInfo: nil, repeats: false)
Here is the code with interstitial
if self.interstitial.isReady {
self.interstitial.presentFromRootViewController(self)
}
NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(1), target: self, selector: "switchScreen", userInfo: nil, repeats: false)
This only returns the user to the view controller and does not continue to the finish view controller.
I tried to call the function on dismissal of the ad
func interstitialDidDismissScreen(interstitial: GADInterstitial!) {
print("interstitialDidDismissScreen")
NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(1), target: self, selector: "switchScreen", userInfo: nil, repeats: false)
}
However that function didn't fire at all.
Am I missing a function or something here?
Here is the switch screen function for reference
func switchScreen() {
let mainStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let vc : finishViewController = mainStoryboard.instantiateViewControllerWithIdentifier("finish") as! finishViewController
vc.yourFinishScore = yourScore
vc.toPass = toPass
self.presentViewController(vc, animated: true, completion: nil)
}
Make sure you've set the interstitial's delegate.
myInterstitial.delegate = self
interstitialDidDismissScreen won't be called if the delegate is not set.
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)
}
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)