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.
Related
Trying to make a timer start as a result of the UIAlert being clicked on. But I keep getting this error indicating the instances isTimerRunning and runTimer cannot be used on the thirdViewController.
We have been trying to move it around, thinking it is a scope issue, but cannot seem to get it to be ok with those functions.
When we adjusted it to use alert.copyAction, rather than let.. the error changes to "expected declaration".
var seconds = 60
var timer = Timer()
var isTimerRunning = false
var resumeTapped = false
let alert = UIAlertController(title: "Your wing was damaged! There is also a dust storm incoming! You need to repair the wing and escape to the next planet.", message: nil, preferredStyle: .alert)
let copyAction = UIAlertAction(title: "Copy that mission control!", style: .default, handler: { action in
if isTimerRunning == false {
runTimer()
}
})
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(thirdViewController.updateTimer)), userInfo: nil, repeats: true)
}
#objc func updateTimer() {
if seconds < 1 {
timer.invalidate()
} else {
seconds -= 1
timeLabel.text = timeString(time: TimeInterval(seconds))
}
}
func timeString(time:TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i”, hours, minutes, seconds")
}
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(withTimeInterval: 0.0, repeats: false) { (timer) in
self.alert.addAction(self.copyAction)
self.present(self.alert,animated: true, completion: nil)
}
}
//use run timer method in alert controller).so you can start timer with open alert
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(withTimeInterval: 0.0, repeats: false) { (timer) in
runtimer()
self.alert.addAction(self.copyAction)
self.present(self.alert,animated: true, completion: nil)
}
}
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
Every time my notification timer goes off it repeats 6 times via in the minute. I only want the notification to fire once per minute. How can I write the code so the notification only goes off once per minute.
import UIKit
class ViewController: UIViewController {
var timer = Timer()
var passingDate : Date?
#IBOutlet var dptext: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
createDatePicker()
timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(ViewController.testDate), userInfo: nil, repeats: true)
}
func createDatePicker() {
datePicker.datePickerMode = .dateAndTime
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneButton], animated: false)
dptext.inputAccessoryView = toolbar
dptext.inputView = datePicker
}
#objc func testDate() {
if Calendar.current.isDate(datePicker.date, equalTo: Date(), toGranularity: .minute) {
print("success")
if let passingDate = passingDate, Calendar.current.isDate(datePicker.date, equalTo: passingDate, toGranularity: .minute) {
// Previous date existing, and is in the same minute as the current date : do nothing
return
}
passingDate = datePicker.date
print("success")
}
}
#objc func donePressed() {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
dptext.text = dateFormatter.string(from: datePicker.date)
self.view.endEditing(true)
}
}
Change the timeInterval from 10 to 60 :
timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(ViewController.testDate), userInfo: nil, repeats: true)
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)