Image appear when timer is at 1 - swift

im making a reaction time app, and I have a label set to count with Seconds. I want to make my image appear when the label is at 1 second, but it doesn't appear. The timer works fine, just the image. Help me in swift please.
import UIKit
class timerViewController: UIViewController {
var go = NSTimeInterval()
var timer = NSTimer()
#IBOutlet weak var tapStop: UIImageView!
#IBOutlet weak var displayTimer: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if displayTimer.text == "00:01:00"{
tapStop.image = UIImage(named: "carcrash")
}
}
#IBAction func stop(sender: UIButton) {
timer.invalidate()
}
#IBAction func start(sender: UIButton) {
if (!timer.valid) {
let test:Selector = "updateTime"
timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: test, userInfo: nil, repeats: true)
go = NSDate.timeIntervalSinceReferenceDate()
}
}
func updateTime(){
var timeNow = NSDate.timeIntervalSinceReferenceDate()
var pass: NSTimeInterval = timeNow - go
let minutes1 = UInt8(pass / 60.0)
pass -= (NSTimeInterval(minutes1) * 60)
let seconds1 = UInt8(pass)
pass -= NSTimeInterval(seconds1)
let milli1 = UInt8(pass * 100)
let minutes2 = String(format: "%02d", minutes1)
let seconds2 = String(format: "%02d", seconds1)
let milli2 = String(format: "%02d", milli1)
displayTimer!.text = "\(minutes2):\(seconds2):\(milli2)"
}
}

You should put this:
if displayTimer.text == "00:01:00"{
tapStop.image = UIImage(named: "carcrash")
}
in your func updateTime() instead of viewDidLoad(), and put them into main thread, so that your image will be updated on the UI. Your func updateTime() will look like this:
func updateTime(){
var timeNow = NSDate.timeIntervalSinceReferenceDate()
var pass: NSTimeInterval = timeNow - go
let minutes1 = UInt8(pass / 60.0)
pass -= (NSTimeInterval(minutes1) * 60)
let seconds1 = UInt8(pass)
pass -= NSTimeInterval(seconds1)
let milli1 = UInt8(pass * 100)
let minutes2 = String(format: "%02d", minutes1)
let seconds2 = String(format: "%02d", seconds1)
let milli2 = String(format: "%02d", milli1)
displayTimer!.text = "\(minutes2):\(seconds2):\(milli2)"
if displayTimer.text == "00:01:00"{
dispatch_async(dispatch_get_main_queue(),{
tapStop.image = UIImage(named: "carcrash")
})
}
}

Related

Countdown Timer with Pause and Stop buttons in Swift

I’m trying to figure out a way to create a countdown timer in Swift that I can pause, stop and resume.
This is my code:
#objc func updateTimer() {
if secondsPassed < totalTime {
secondsPassed += 1
progressBar.progress = Float(secondsPassed) / Float(totalTime)
let minutes = String(totalTime / 60)
let seconds = String(totalTime % 60)
countDownLabel.text = minutes + ":" + seconds
totalTime -= 1
} else {
timer.invalidate()
titleLabel.text = "Done!"
let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
I already have a progress bar, but I can’t set up the countdown timer properly. When I run this code, I get 0:3 instead of 0:03. Another problem is that it doesn’t stop at 0:00. It just freezes before that.
Here’s the entire code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var progressBar: UIProgressView!
#IBOutlet weak var titleLabel: UILabel!
// testando countdownlabel
#IBOutlet weak var countDownLabel: UILabel!
let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 5]
var totalTime = 0
var player: AVAudioPlayer!
var secondsPassed = 0
var timer = Timer()
#IBAction func hardnessSelected(_ sender: UIButton) {
timer.invalidate()
let hardness = sender.currentTitle!
totalTime = eggTimes[hardness]!
progressBar.progress = 0.0
secondsPassed = 0
titleLabel.text = hardness
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
}
#objc func updateTimer() {
if secondsPassed < totalTime {
secondsPassed += 1
progressBar.progress = Float(secondsPassed) / Float(totalTime)
let minutes = String(totalTime / 60)
let seconds = String(totalTime % 60)
countDownLabel.text = minutes + ":" + seconds
totalTime -= 1
} else {
timer.invalidate()
titleLabel.text = "Done!"
let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
}

UISwitch saving values to use in a function

When the user turns switch on, I would like a random value to display on a UILabel, then take that same random value, and use it to multiply and find another value. I think my problem is that I am trying to use a let statement to hold the value, then trying to call back to that let value from another function, but I don't know another way to to this.
I already can get the random value to appear on a UILabel after the switch is active. Then when the switch is not active, a value of 0 is left on the UILabel.
The IBOutlet for the switch:
#IBOutlet weak var tipSwitch: UISwitch!
This is the action for the switch:
#IBAction func switchChanged(_ sender: UISwitch) {
if sender.isOn{
sender.setOn(false, animated: true)
percentPlaceholder.text! = String(0) + "%"
}
else{
sender.setOn(true, animated: true)
let randomTip = Int.random(in: 1...100)
percentPlaceholder.text! = String(randomTip)
calculateTipSwitch()
}
}
This is the calculateTipSwitch function:
func calculateTipSwitch() {
var tipAmountSwitch = Float()
var totalCostSwitch = Float()
if let billAmountSwitch = Float(billCost.text!) {
tipAmountSwitch = billAmountSwitch * randomTip / 100
totalCostSwitch = tipAmountSwitch + billAmountSwitch
}
else {
tipAmountSwitch = 0
totalCostSwitch = 0
}
tipDollarAmt.text! = String(format: "%.2f", tipAmountSwitch)
totalBill.text! = String(format: "%.2f", totalCostSwitch)
}
Here is all of my code if you want a better understanding of what I'm trying to accomplish:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var billCost: UITextField!
#IBOutlet weak var percentPlaceholder: UILabel!
#IBOutlet weak var tipDollarAmt: UILabel!
#IBOutlet weak var totalBill: UILabel!
#IBOutlet weak var tipSlider: UISlider!
#IBOutlet weak var tipSegment: UISegmentedControl!
#IBOutlet weak var tipStepper: UIStepper!
#IBOutlet weak var tipSwitch: UISwitch!
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let allowed = CharacterSet(charactersIn: ".1234567890")
return string.rangeOfCharacter(from: allowed) != nil
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
billCost.resignFirstResponder()
return true
}
override func viewDidLoad() {
super.viewDidLoad()
percentPlaceholder.text = ""
tipDollarAmt.text = ""
totalBill.text = ""
}
#IBAction func sliderChanged(_ sender: UISlider) {
percentPlaceholder.text! = String(Int(sender.value)) + "%"
tipStepper.value = Double(Int(tipSlider.value))
calculateTip()
}
#IBAction func selectorChanged(_ sender: UISegmentedControl) {
}
#IBAction func stepperChanged(_ sender: UIStepper) {
percentPlaceholder.text! = String(sender.value) + "%"
tipSlider.value = Float(tipStepper.value)
calculateTipStep()
}
#IBAction func switchChanged(_ sender: UISwitch) {
if sender.isOn{
sender.setOn(false, animated: true)
percentPlaceholder.text! = String(0) + "%"
}
else{
sender.setOn(true, animated: true)
let randomTip = Int.random(in: 1...100)
percentPlaceholder.text! = String(randomTip)
}
}
func calculateTip()
{
var tipAmount = Float()
var totalCost = Float()
if let billAmount = Float(billCost.text!) {
tipAmount = billAmount * tipSlider.value / 100
totalCost = tipAmount + billAmount
}
else {
tipAmount = 0
totalCost = 0
}
tipDollarAmt.text! = String(format: "%.2f", tipAmount)
totalBill.text! = String(format: "%.2f", totalCost)
}
func calculateTipStep() {
var tipAmountStep = Float()
var totalCostStep = Float()
if let billAmountStep = Float(billCost.text!) {
tipAmountStep = billAmountStep * Float(tipStepper.value) / 100
totalCostStep = tipAmountStep + billAmountStep
}
else {
tipAmountStep = 0
totalCostStep = 0
}
tipDollarAmt.text! = String(format: "%.2f", tipAmountStep)
totalBill.text! = String(format: "%.2f", totalCostStep)
}
func calculateTipSwitch() {
var tipAmountSwitch = Float()
var totalCostSwitch = Float()
if let billAmountSwitch = Float(billCost.text!) {
tipAmountSwitch = billAmountSwitch * randomTip / 100
totalCostSwitch = tipAmountSwitch + billAmountSwitch
}
else {
tipAmountSwitch = 0
totalCostSwitch = 0
}
tipDollarAmt.text! = String(format: "%.2f", tipAmountSwitch)
totalBill.text! = String(format: "%.2f", totalCostSwitch)
}
}
Basically my problem is that I can't use that random number in another function, so I just need help on how to call back to that randomTip.
You can add a parameter to calculateTipSwitch, and pass the random number as an argument to the calculateTipSwitch method. Change calculateTipSwitch to:
func calculateTipSwitch(tipPercentage: Int) {
var tipAmountSwitch = Float()
var totalCostSwitch = Float()
if let billAmountSwitch = Float(billCost.text!) {
tipAmountSwitch = billAmountSwitch * tipPercentage / 100.0
totalCostSwitch = tipAmountSwitch + billAmountSwitch
}
else {
tipAmountSwitch = 0
totalCostSwitch = 0
}
tipDollarAmt.text! = String(format: "%.2f", tipAmountSwitch)
totalBill.text! = String(format: "%.2f", totalCostSwitch)
}
Then, in switchChanged:
let randomTip = Int.random(in: 1...100)
percentPlaceholder.text! = String(randomTip)
calculateTipSwitch(tipPercentage: randomTip)
In the switchChanged() function , you set the randomTip to percentPlaceholder.text , so in the other functions , you could just call for it.
let randomTip = percentPlaceholder.text
Or another way to do this, is to declare the randomTip variable outside the function, as a property of the class.
class ViewController : UIViewController {
//IBOutlets here
var randomTip : String?
//functions here
}
Then when you set a value to it in switchChanged(), it can be called in the other functions.

app reverts all input variables to defaults after some time

I wrote my fist app, very simple, that creates a user defined number of badges at random times during a user defined window of time. It works fine but after some time (not sure how long, 2-4 hours), all of the user input information reverts to the defaults of the program. The issue is it is supposed to run each day but it is annoying to have to set it each morning. I am not sure if this is a coding issue or if the app 'reboots' when it is not doing anything in the background. Note that this occurs on my iPhone 8 but not on the simulator (or I am not patient enough for it to occur on the simulator).
I have put several print and label to try to identify when it occurs; I am sure I am putting them in the correct places. I apologize for including so much code - I tried to weed some of the mistakes out but I do not know where the problem is.
import UserNotifications
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var EarlyTimePicker: UITextField!
#IBOutlet weak var LateTimePicker: UITextField!
#IBOutlet weak var NumQuestions: UITextField!
#IBOutlet weak var myLabel_Questions: UILabel!// Attached to the label box
#IBOutlet weak var myLabel_StartEndTime: UILabel!
#IBOutlet weak var myLabel_TestResetTime: UILabel!
#IBOutlet weak var myLabel_CurrentEarlyTime: UILabel!
private var earlyTimePicker: UIDatePicker?
private var lateTimePicker: UIDatePicker?
override func viewDidLoad() {
super.viewDidLoad()
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in //ask for permission in order to show messages on the lock screen
if granted {
print("Yay!")
} else {
print("D'oh")
}
}
earlyTimePicker = UIDatePicker()
earlyTimePicker?.datePickerMode = .time //change to .time
earlyTimePicker?.addTarget(self, action: #selector(ViewController.earlyTimeChanged(earlyTimePicker:)),for: .valueChanged)
lateTimePicker = UIDatePicker()
lateTimePicker?.datePickerMode = .time //change to .time
lateTimePicker?.addTarget(self, action: #selector(ViewController.lateTimeChanged(lateTimePicker:)),for: .valueChanged)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.viewTapped(gestureRecognizer:)))
view.addGestureRecognizer(tapGesture)
EarlyTimePicker.inputView = earlyTimePicker
LateTimePicker.inputView = lateTimePicker
}
#objc func viewTapped(gestureRecognizer: UITapGestureRecognizer){
view.endEditing(true)
}
var earlyTime=480
var earlyTimehour=0
var earlyTimeminute=0
#objc func earlyTimeChanged(earlyTimePicker: UIDatePicker){
let earlyTimeFormatter = DateFormatter()
earlyTimeFormatter.dateFormat = "h:mm a"
earlyTimeFormatter.amSymbol = "AM"
earlyTimeFormatter.pmSymbol = "PM"
EarlyTimePicker.text = earlyTimeFormatter.string(from: earlyTimePicker.date)
view.endEditing(true)
let earlyTimedate = earlyTimePicker.date
let earlyTimecomponents = Calendar.current.dateComponents([.hour, .minute], from: earlyTimedate)
earlyTimehour = earlyTimecomponents.hour!
earlyTimeminute = earlyTimecomponents.minute!
earlyTime = earlyTimecomponents.hour! * 60 + earlyTimecomponents.minute!
print("earlyTimehour: \(earlyTimecomponents.hour!)")
print("earlyTimeminute: \(earlyTimecomponents)")
print("earlyTime: \(earlyTime)")
print("Current Time: \(Date())")
}
var lateTime=1200
var lateTimehour=0
var lateTimeminute=0
#objc func lateTimeChanged(lateTimePicker: UIDatePicker){
let lateTimeFormatter = DateFormatter()
lateTimeFormatter.dateFormat = "h:mm a"
lateTimeFormatter.amSymbol = "AM"
lateTimeFormatter.pmSymbol = "PM"
LateTimePicker.text = lateTimeFormatter.string(from: lateTimePicker.date)
view.endEditing(true)
let lateTimedate = lateTimePicker.date
let lateTimecomponents = Calendar.current.dateComponents([.hour, .minute], from: lateTimedate)
lateTimehour = lateTimecomponents.hour!
lateTimeminute = lateTimecomponents.minute!
lateTime = lateTimecomponents.hour! * 60 + lateTimecomponents.minute!
let testMinute = lateTime % 60
let testHour = lateTime / 60
print("lateTimehour: \(lateTimecomponents.hour!)")
print("lateTimeminute: \(lateTimecomponents)")
print("lateTime: \(lateTime)")
print("testHour: \(testHour)")
print("testMinute: \(testMinute)")
myLabel_TestResetTime.text = "Time Set \(Date())"
myLabel_CurrentEarlyTime.text = "Current Early Time: \(earlyTime) / OnOff: \(OnOff)"
}
let PickedString = ["One","Two","Three","Four", "Five","Six","Seven","Eight"]
// #IBAction func TestCallFunction(_ sender: UIButton) {
// scheduleLocal()
// }
//NEED TO REPEAT THIS FUNCTION AT EARLY TIME - 10
//need to stop repeating with a cancel button (while bool true, do it, while false, stop. Default is false)
var RunDaily: Timer?
var OnOff = false
var QuestionNum = 1
#IBAction func Launch(_ sender: UIButton) {
OnOff = true
let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests()
guard let QuestionNumA = Int(NumQuestions.text!) else { //This is how to get the UserInterface VALUE as a number
print("not a number!: \(String(describing: NumQuestions.text))")
return
}
print("Number of Questions: \(QuestionNumA)")
// var QuestionNum = 1
if QuestionNumA > 10 {QuestionNum=10} else {QuestionNum=QuestionNumA}
print("QuestionNumA:\(QuestionNumA) vs QuestionNum: \(QuestionNum)")
printStuff()
showMessage()
}
#IBAction func Stop(_ sender: UIButton) {
OnOff = false
printStuff()
}
func printStuff() {
if OnOff == true {
print("Bool is On : \(OnOff)")
RunDaily = Timer.scheduledTimer(timeInterval: 86400, target: self, selector: #selector(showMessage), userInfo: nil, repeats: true)//86400
}
if OnOff == false {
print("Bool is Off : \(OnOff)")
RunDaily?.invalidate()
let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests()
}
}
func SaveDefaultData(){ // THis is the structure to SAVE input data for when the app relaunches (causes error when run.
let defaults = UserDefaults.standard
defaults.set("Date()", forKey:"key1")
//defaults.set(earlyTimePicker, forKey:"earlyTimePickerSet") cannot set earlyTimePicker. causes crash
// defaults.set(lateTimePicker, forKey:"lateTimePickerSet")
defaults.set(earlyTime, forKey:"earlyTimeSet")
defaults.set(lateTime, forKey:"lateTimeSet")
defaults.set(QuestionNum, forKey:"QuestionNumSet")
}
func SetDefaultData(){// THis is the structure to Set input for when the app relaunches
let defaults = UserDefaults.standard
if let savedValue = defaults.string(forKey: "key1"){
print("Here you will get saved value \(savedValue)")
} else {
print("No value in Userdefault,Either you can save value here or perform other operation")
defaults.set("Here you can save value", forKey: "key1")
}
if let earlyTimeValue = defaults.string(forKey: "earlyTimeSet"){
print("Here you will get saved value \(earlyTimeValue)")
earlyTime = UserDefaults.standard.value(forKey: "earlyTimeSet") as? Int ?? 485
} else {
print("No value in Userdefault,Either you can save value here or perform other operation")
defaults.set("Here you can save value", forKey: "earlyTimeSet")
earlyTime = 500
}
if let lateTimeValue = defaults.string(forKey: "lateTimeSet"){
print("Here you will get saved value \(lateTimeValue)")
lateTime = UserDefaults.standard.value(forKey: "lateTimeSet") as? Int ?? 1265
} else {
print("No value in Userdefault,Either you can save value here or perform other operation")
defaults.set("Here you can save value", forKey: "lateTimeSet")
lateTime = 1230
}
if let QuestionNumValue = defaults.string(forKey: "QuestionNumSet"){
print("Here you will get saved value \(QuestionNumValue)")
QuestionNum = UserDefaults.standard.value(forKey: "QuestionNumSet") as? Int ?? 4
} else {
print("No value in Userdefault,Either you can save value here or perform other operation")
defaults.set("Here you can save value", forKey: "QuestionNumSet")
QuestionNum = 2
}
}
#objc func showMessage() {
let center = UNUserNotificationCenter.current()
if lateTime <= earlyTime {
lateTime = earlyTime+1
if earlyTimehour <= 12 {
LateTimePicker.text = "\(earlyTimehour):\(earlyTimeminute) AM"
}
if earlyTimehour > 12 {
let EarlyTimeAfternoon = earlyTimehour - 12
LateTimePicker.text = "\(EarlyTimeAfternoon):\(earlyTimeminute) PM"
}
}
// center.removeAllPendingNotificationRequests()
// THIS IS WHERE ALL THE USER INPUT GETS INTO THE PROGRAM //
// guard let QuestionNumA = Int(NumQuestions.text!) else { //This is how to get the UserInterface VALUE as a number
// print("not a number!: \(String(describing: NumQuestions.text))")
// return
// }
//print("Number of Questions: \(QuestionNumA)")
// THIS IS WHERE ALL THE USER INPUT GETS INTO THE PROGRAM //
var RandHourArray:[Int] = [0]
var RandMinArray:[Int] = [0]
var RandQuestionArray:[Int] = [0]
var Counter = 1
// var QuestionNum = 1
//if QuestionNumA > 2 {QuestionNum=10} else {QuestionNum=QuestionNumA}
// print("QuestionNumA:\(QuestionNumA) vs QuestionNum: \(QuestionNum)")
for _ in 0 ... QuestionNum-1{
// Pick random times for badges
//let RandHour = Int.random(in: earlyTimehour ... lateTimehour)
let RandTimeMinFromMidnight = Int.random(in: self.earlyTime ... self.lateTime)
let ConvertRandTimeHours = RandTimeMinFromMidnight / 60
let ConvertRandTimeMinutes = RandTimeMinFromMidnight % 60
RandHourArray.append(ConvertRandTimeHours)
//let RandMin = Int.random(in: earlyTimeminute ... lateTimeminute)
RandMinArray.append(ConvertRandTimeMinutes)
let RandQuestion = Int.random(in: 0 ... self.PickedString.count-1)
RandQuestionArray.append(RandQuestion)
//print("RandTimeMinFromMidnight: \(RandTimeMinFromMidnight)")
// print("RandHourArray: \(RandHourArray)")
// print("ConvertRandTimeHours: \(ConvertRandTimeHours)")
// print("RandMinArray: \(RandMinArray)")
// print("ConvertRandTimeMinutes: \(ConvertRandTimeMinutes)")
}
myLabel_Questions.text = "# of questions: \(QuestionNum)"//\(QuestionNumA)"
myLabel_StartEndTime.text = "Start Time \(earlyTime) / End Time \(lateTime)"
let content_A = UNMutableNotificationContent()
content_A.title = "Prompt"
content_A.body = self.PickedString[RandQuestionArray[Counter]] //
content_A.categoryIdentifier = "alarm"
content_A.userInfo = ["customData": "fizzbuzz"]
content_A.sound = UNNotificationSound.default
var dateComponents_A = DateComponents()
dateComponents_A.hour = RandHourArray[Counter]
dateComponents_A.minute = RandMinArray[Counter]
let trigger_A = UNCalendarNotificationTrigger(dateMatching: dateComponents_A, repeats: false)
let request_A = UNNotificationRequest(identifier: UUID().uuidString, content: content_A, trigger: trigger_A)
center.add(request_A)
print("Request A time: \(RandHourArray[Counter]) : \(RandMinArray[Counter])")
print("Question String picked A: \(self.PickedString[RandQuestionArray[Counter]])")
Counter=2
if Counter<=QuestionNum {
let content_B = UNMutableNotificationContent()
content_B.title = "Prompt"
content_B.body = self.PickedString[RandQuestionArray[Counter]]
content_B.categoryIdentifier = "alarm"
content_B.userInfo = ["customData": "fizzbuzz"]
content_B.sound = UNNotificationSound.default
var dateComponents_B = DateComponents()
dateComponents_B.hour = RandHourArray[Counter]
dateComponents_B.minute = RandMinArray[Counter]
let trigger_B = UNCalendarNotificationTrigger(dateMatching: dateComponents_B, repeats: false)
let request_B = UNNotificationRequest(identifier: UUID().uuidString, content: content_B, trigger: trigger_B)
center.add(request_B)
print("Request B time: \(RandHourArray[Counter]) : \(RandMinArray[Counter])")
print("Question String picked B: \(self.PickedString[RandQuestionArray[Counter]])")
}
}
}
You should store your data inside UserDefaults, Keychain and Core Data or other stuff. if you dont store your data every time you close the application all the data will deallocate from the memory because they were stored in the heap.
Unsaved data:
let myLabel: UILabel = UILabel()
myLabel.text = "Some text"
Should save like:
UserDefaults.standard.setValue(myLabel.text, forKey: "it.is.custom")
And load like:
myLabel.text = UserDefaults.standard.value(forKey: "it.is.custom") as? String
refrence to study: https://fluffy.es/persist-data/

Saving HighScore in Swift 4

This code has all my labels Im trying to use. I can't save the High score and implement it into the game. Now its saying I need to type more so i'm just going to keep typing until it tells me i'm good. It still hasn't told me i'm goo i'm actually very surprised wow.
import UIKit
import CoreData
import SpriteKit
var timer:Timer?
var seconds:Int = 5
var maxSeconds: Int = 5
var totalPoints:Int = 0
var high:Int = 0
let userDefaults = UserDefaults.standard
let defaults = UserDefaults.standard
class ViewController: UIViewController {
#IBOutlet weak var menu: UIButton!
var i = 0
var point = 0
#IBOutlet weak var highScore: UILabel!
#IBOutlet weak var timeLabel:UILabel?
#IBOutlet weak var points:UILabel?
#IBOutlet weak var totalPoint: UILabel!
#objc func tapped(){
i += 1
switch i {
case 1:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.error)
case 2:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.success)
case 3:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.warning)
case 4:
let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()
case 5:
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccurred()
case 6:
let generator = UIImpactFeedbackGenerator(style: .heavy)
generator.impactOccurred()
default:
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
i = 0
}
}
func updateTimeLabel()
{
if(timeLabel != nil)
{
let sec:Int = seconds % 30
let sec_p:String = String(format: "%02d", sec)
timeLabel!.text = "\(sec_p)"
}
}
#objc func onUpdateTimer() -> Void
{
if(seconds > 0 && seconds <= maxSeconds)
{
seconds -= 1
updateTimeLabel()
}
else if(seconds == 0)
{
if(timer != nil)
{
timer!.invalidate()
timer = nil
userDefaults.set(totalPoints, forKey: "totalPoints")
let alertController = UIAlertController(title: "Time Up!", message: "Your time is up! You got a score of \(point) points and your total coins now is \(totalPoints). You Can Do Better", preferredStyle: .alert)
let restartAction = UIAlertAction(title: "Play Again!", style: .default, handler: nil)
alertController.addAction(restartAction)
let FirstSubview = alertController.view.subviews.first
let AlertContentView = FirstSubview?.subviews.first
for subview in (AlertContentView?.subviews)! {
subview.backgroundColor = UIColor(red: 226/255.0, green: 158/255.0, blue: 152/255.0, alpha: 5.0)
subview.layer.cornerRadius = 1
subview.alpha = 1
}
self.present(alertController, animated: true, completion: nil)
point = 0
seconds = maxSeconds
updateTimeLabel()
menu.isHidden = false
defaults.set(high, forKey: "high")
}
}
}
#IBAction func Restart(_ sender: Any) {
}
#IBAction func adder(_ sender: Any)
{
point += 1
points?.text = "\(point)"
if point % 10 == 0 {
totalPoints = 10 + totalPoints
totalPoint?.text = String(totalPoints)
}
if(timer == nil)
{
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector:#selector(onUpdateTimer), userInfo:nil, repeats:true)
}
tapped()
menu.isHidden = true
}
override func viewDidLoad() {
points?.text = "\(point)"
let total = userDefaults.integer(forKey: "totalPoints")
if total != 0 {
totalPoints = total
} else {
totalPoints = 0
}
let score = defaults.integer(forKey: "high")
if high < point {
high = score
} else {
high = 0
}
totalPoint?.text = String(totalPoints)
updateTimeLabel()
highScore.text = String(high)
}
}
Do I need to put something at the end? Well it looks like that didn't work either!
#for example
func saveHighScore() {
UserDefaults.standard.set(score, forKey: "HIGHSCORE")
}

Using NSCore and NSKeyedArchiver with SWIFT

I been trying to get persistent data on my app to have a history of user entries. After I store my data in to array I want to archive it, and after I unarchive it i get weird value instead of what i want to see.
Here is my class for where i store my data
import Foundation
class MyHistory: NSObject, NSCoding {
var kicksNumber: Int
var durationNumber: Int
init(kicksNumber: Int,durationNumber: Int) {
self.kicksNumber = kicksNumber
self.durationNumber = durationNumber
}
required init(coder decoder: NSCoder) {
kicksNumber = decoder.decodeObjectForKey("kicksNumber") as! Int
durationNumber = decoder.decodeObjectForKey("durationNumber") as! Int
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(self.kicksNumber, forKey: "kicksNumber")
coder.encodeObject(self.durationNumber, forKey: "durationNumber")
}
}
Then here is my class where things happen, And where I am testing out the save and load process.
class Kicks: UIViewController {
var myHistoryArray: [MyHistory] = []
var currentMyHistory: MyHistory!
var newHistory = [MyHistory]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = UIColor(patternImage: UIImage(named: "background13.png")!)
let defaults = NSUserDefaults.standardUserDefaults()
if let savedPeople = defaults.objectForKey("MyHistory") as? NSData {
newHistory = NSKeyedUnarchiver.unarchiveObjectWithData(savedPeople) as! [MyHistory]
//print("this is archived ", newHistory[0])
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var count = 0 as Int
var countKicks = 0 as Int
var kickReached = false as Bool
var pressedOnce = true as Bool
var timer = NSTimer()
var test: MyHistory!
#IBOutlet var timerLabel: UITextField!
#IBOutlet var kicksLabel: UITextField!
#IBAction func kickButton() {
//currentMyHistory.kicksNumber = 5
if pressedOnce {
pressedOnce = false
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("counter"), userInfo: nil, repeats: true)
} else if kickReached {
// let date = NSDate()
// let calendar = NSCalendar.currentCalendar()
// let timer_total = calendar.components([ .Hour, .Minute, .Second], fromDate: date)
} else if !pressedOnce {
countKicks++
kicksLabel.text = "\(countKicks)"
if countKicks == 10 {
kickReached = true
timer.invalidate()
congratsAlert()
currentMyHistory = MyHistory(kicksNumber: 5, durationNumber: 10)
print("this is currentMyHistory", currentMyHistory.kicksNumber )
myHistoryArray.append(currentMyHistory)
test = myHistoryArray[0]
print("this is myHistoryArray0", test.kicksNumber)
//save data
let savedData = NSKeyedArchiver.archivedDataWithRootObject(myHistoryArray)
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(savedData, forKey: "MyHistory")
//load data
//let defaults = NSUserDefaults.standardUserDefaults()
// let person = people[indexPath.item]
//let historyUnarchived = NSKeyedUnarchiver.unarchiveObjectWithFile("/path/to/archive") as? [MyHistory]
// let data1 = NSUserDefaults.standardUserDefaults().objectForKey("myHistoryArray")
print("this is unrachived",newHistory[0])
clear()
}
}
}
// save countKicks, count, and stamp i
func congratsAlert() {
let alert = UIAlertController(title: "Congratulation", message: "Yay!!! Angelina kicked 10 times in less than 2 hours.",preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok",style: .Default,handler:{(action:UIAlertAction) -> Void in})
alert.addAction(okAction)
presentViewController(alert,animated: true,completion: nil)
}
func clear() {
count = 0
countKicks = 0
kickReached = false
pressedOnce = true
timerLabel.text = "00:00:0\(count)"
kicksLabel.text = "\(countKicks)"
}
func counter() {
++count
let (hour,minutes,seconds) = secondsToHoursMinutesSeconds(count)
if seconds < 10 && minutes < 10 {
timerLabel.text = "0\(hour):0\(minutes):0\(seconds)"
} else if seconds > 9 && minutes < 10 {
timerLabel.text = "0\(hour):0\(minutes):\(seconds)"
} else if seconds > 9 && minutes > 9 {
timerLabel.text = "0\(hour):\(minutes):\(seconds)"
} else if seconds < 10 && minutes > 9 {
timerLabel.text = "0\(hour):\(minutes):0\(seconds)"
}
}
func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int) {
return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
}
/*
func savePlaces() {
let placesArray = [myHistory(kicksNumber: 420, durationNumber: 89)]
let placesData = NSKeyedArchiver.archivedDataWithRootObject(placesArray)
NSUserDefaults.standardUserDefaults().setObject(placesData, forKey: "kicks")
}
func loadPlaces() {
let placesData = NSUserDefaults.standardUserDefaults().objectForKey("kicks") as? NSData
if let placesData = placesData {
let placesArray = NSKeyedUnarchiver.unarchiveObjectWithData(placesData) as? [myHistory]
if let placesArray = placesArray {
// do something…
}
}
}*/
}
My output is like this:
this is currentMyHistory 5
this is myHistoryArray0 5
this is unrachived
Message from debugger: Terminated due to signal 15
why is unarchived is weird value?
In your MyHistory class you are using ints, so in your encodeWithCoder function you should be using
coder.encodeInteger(self.kicksNumber, forKey: "kicksNumber")
coder.encodeInteger(self.durationNumber, forKey: "durationNumber")
Likewise for your decoder you should be using decodeIntForKey, not decodeObjectForKey.
kicksNumber = decoder.decodeIntegerForKey("kicksNumber")
durationNumber = decoder.decodeIntegerForKey("durationNumber")