Applying an NSTimer to a UILabel (Swift) - swift

i'm quite new to using swift and i'm currently working on a small school project. However, one function i cant seem to work out is how to make an NSTimer change the text in a UILabel after a certain amount of time. I want to apply this function to a UILabel (cannotbuy) that was blank, and had just been changed to text displaying a message("you dont have enough points"), and i want this message to be removed and the UILabel to be blank again after a second or so. Can anyone help me? Thanks.
class Upgrades: UIViewController{
#IBOutlet weak var shprogresslabel: UILabel!
#IBOutlet weak var fsprogresslabel: UILabel!
#IBOutlet weak var shprogress: UIProgressView!
#IBOutlet weak var fsprogress: UIProgressView!
#IBOutlet weak var shbutton: UIButton!
#IBOutlet weak var fsbutton: UIButton!
#IBOutlet weak var storepoints: UILabel!
#IBOutlet weak var cannotbuy: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label1: UILabel!
var fsprice = Int()
var shprice = Int()
let defaults = NSUserDefaults.standardUserDefaults()
func updateProgress1(){
fsprogress.progress += 0.1
let fsprogressvalue = self.fsprogress.progress
fsprogresslabel.text = "\(fsprogressvalue * 100)%"
}
func updateProgress2(){
shprogress.progress += 0.2
let shprogressvalue = self.shprogress.progress
shprogresslabel.text = "\(shprogressvalue * 100)%"
}
#IBAction func button2(sender: AnyObject) {
if shprice <= 90{
if SharingManager.sharedInstance.totalscore >= shprice{
SharingManager.sharedInstance.shiphealth = SharingManager.sharedInstance.shiphealth + 1
SharingManager.sharedInstance.totalscore = SharingManager.sharedInstance.totalscore - fsprice
storepoints.text = String(SharingManager.sharedInstance.totalscore)
shprice = shprice + 20
print(shprice)
label2.text = ("\(shprice)")
defaults.setInteger(SharingManager.sharedInstance.shiphealth, forKey: "SharingManager.sharedInstance.shiphealth")
updateProgress2()
}else{
cannotbuy.text = "You dont have enough points"
}
}else{
cannotbuy.text = "You have purchased all the available upgrades for this"
}
}
#IBAction func button1(sender: AnyObject) {
if fsprice <= 100{
if SharingManager.sharedInstance.totalscore >= fsprice{
SharingManager.sharedInstance.bulletspeed = SharingManager.sharedInstance.bulletspeed - 0.15
SharingManager.sharedInstance.totalscore = SharingManager.sharedInstance.totalscore - fsprice
storepoints.text = String(SharingManager.sharedInstance.totalscore)
fsprice = fsprice + 10
print(fsprice)
label1.text = ("\(fsprice)")
defaults.setDouble(SharingManager.sharedInstance.bulletspeed, forKey: "SharingManager.sharedInstance.bulletspeed")
updateProgress1()
}else{
cannotbuy.text = "You dont have enough points"
}
}else{
cannotbuy.text = "You have purchased all the available upgrades for this"
}
}
override func viewDidLoad() {
if fsprice == 0{
fsprice = 10
}
if shprice == 0{
shprice = 10
}
if fsprice == 180{
fsbutton.enabled = false
}
if shprice == 100{
shbutton.enabled = false
}
storepoints.text = String(SharingManager.sharedInstance.totalscore)
label1.text = ("\(fsprice)")
label2.text = ("\(shprice)")
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

There are two ways for you to do this:
Using NSTimer:
#IBAction func button2(sender: AnyObject) {
...
cannotbuy.text = "You don't have enough points"
NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: #selector(ViewController.resetCannotBuy), userInfo: nil, repeats: false)
}
func resetCannotBuy() {
cannotbuy.text = ""
}
Using dispatch_after:
#IBAction func button2(sender: AnyObject) {
...
cannotbuy.text = "You don't have enough points"
let fiveSecondLater = dispatch_time(DISPATCH_TIME_NOW, 5 * Int64(NSEC_PER_SEC))
dispatch_after(fiveSecondLater, dispatch_get_main_queue()) {
self.cannotbuy.text = ""
}
}
NSEC_PER_SEC is the constant for nanosecond per second, which is equal to 1 billion.

Related

Swift: Tracking User's score

I'm trying to create a Quiz app that consists of two buttons, false and true button. My question is, as I answer more questions in the app, I want the textLabel to keep track of my score. And then when I circle back to the first question again, it should reset. This is my code so far. I'm looking forward to your answers.
class ViewController: UIViewController {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var progressBar: UIProgressView!
#IBOutlet weak var trueButton: UIButton!
#IBOutlet weak var falseButton: UIButton!
#IBOutlet weak var scoreLabel: UILabel!
var quizBrain = QuizBrain()
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
progressBar.progress = 0.0
}
#IBAction func answerButtonPressed(_ sender: UIButton) {
let userAnswer = sender.currentTitle
let userGotItRight = quizBrain.checkAnswer(userAnswer!)
if userGotItRight {
sender.shortChangeTo(.green)
} else {
sender.shortChangeTo(.red)
}
quizBrain.nextQuestion()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.updateUI()
}
}
func updateUI() {
questionLabel.text = quizBrain.getQuestionText()
trueButton.backgroundColor = UIColor.clear
falseButton.backgroundColor = UIColor.clear
progressBar.progress = 33
scoreLabel.text = "Score: \(quizBrain.getScore)"
}
}
You don't have any code for it yet? You can create a struct like user
struct user {
var score: Int = 0
mutating func answerRight (){
self.score =+ 1 }
mutating func reset (){
self.score = 0 }
}
But I see this in your code "Score: (quizBrain.getScore)"
This says that quizBrain should know the score. But you never add a value to it So check your quizBrain and create a function or an object that can track the score and then call it here "if userGotItRight {}"

Error instantiating View Controller

When I try to instantiate my ViewController with the code below (in the viewDidLoad part) I get a Thread 1: EXC_BAD_ACCESS when running the app on the self.present line. (I'm a beginner to coding)
EDIT: So I provide my entire code here to see where it goes wrong. I shifted the code to viewDidLoad of my Second View Controller now. Now the app starts up, however when I press the "enter" Button, I get a "Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value" error..
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var progressBarView: ProgressBarView!
#IBOutlet weak var progressBarView1: ProgressBarView1!
override func viewDidLoad() {
super.viewDidLoad()
// updaten van de progressbar
progressBarView.progress = CGFloat(percProgress())
progressBarView1.progress = CGFloat(0.5)
// een constante maken die de daystogocalc Int van de berekening verderop in een String cast
let daysToGoCalcString = String(daysToGoCalc())
// updaten van het label daysToGo
daysToGo.text = "Still \(daysToGoCalcString) days to go"
// updaten van het label textPercentage
let textPercentage = NSString(format: "%.0f", (percProgress() * 100))
percentageDays.text = String(textPercentage) + "%"
}
#IBOutlet weak var daysToGo: UILabel!
#IBOutlet weak var percentageDays: UILabel!
#IBOutlet weak var firstGoalLabel: UILabel!
#IBAction func unwindToGoals(unwindSegue: UIStoryboardSegue) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Automatische datumberekening
let today = Date()
let calendar = Calendar.current
// Dagnummer van het jaar
var todayNumber: Int {
get {
return calendar.ordinality(of: .day, in: .year, for: today)!
}
}
// FLOAT MAKER: onderstaande maakt een Float van het dagnummer (nodig voor de Progress Bar uiteindelijk)
var todayFloat: Float {
get {
return Float(todayNumber)
}
}
// KWARTAAL PROGRESSIE: deze functie checkt eerst in welk kwartaal je zit, en vervolgens de voortgang in dat kwartaal in een float
func percProgress() -> Float {
if todayNumber < 91 {
return todayFloat / 90
}
else if todayNumber < 182 {
return (todayFloat - 90) / 91
}
else if todayNumber < 274 {
return (todayFloat - 181) / 92
}
else {
return (todayFloat - 273) / 92
}
}
// Bereken aantal dagen te gaan in kwartaal
func daysToGoCalc() -> Int {
if todayNumber < 91 {
return 90 - todayNumber
}
else if todayNumber < 182 {
return 181 - todayNumber
}
else if todayNumber < 274 {
return 273 - todayNumber
}
else {
return 365 - todayNumber
}
}
}
// SECOND VIEW CONTROLLER
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
firstGoaltext.delegate = self
firstGoalStart.delegate = self
firstGoalEnd.delegate = self
secondGoaltext.delegate = self
secondGoalStart.delegate = self
secondGoalEnd.delegate = self
thirdGoaltext.delegate = self
thirdGoalStart.delegate = self
thirdGoalEnd.delegate = self
fourthGoaltext.delegate = self
fourthGoalStart.delegate = self
fourthGoalEnd.delegate = self
fifthGoaltext.delegate = self
fifthGoalStart.delegate = self
fifthGoalEnd.delegate = self
// INSTANTIATE VIEWCONTROLLER
let storyboard1 = UIStoryboard(name: "Main", bundle: nil)
var firstController: UIViewController {
get {
return storyboard1.instantiateViewController(withIdentifier: "myViewControllerIdentifier")
}
}
self.present(firstController, animated: true, completion: nil)
}
#IBOutlet weak var firstGoaltext: UITextField!
#IBOutlet weak var firstGoalStart: UITextField!
#IBOutlet weak var firstGoalEnd: UITextField!
#IBOutlet weak var secondGoaltext: UITextField!
#IBOutlet weak var secondGoalStart: UITextField!
#IBOutlet weak var secondGoalEnd: UITextField!
#IBOutlet weak var thirdGoaltext: UITextField!
#IBOutlet weak var thirdGoalStart: UITextField!
#IBOutlet weak var thirdGoalEnd: UITextField!
#IBOutlet weak var fourthGoaltext: UITextField!
#IBOutlet weak var fourthGoalStart: UITextField!
#IBOutlet weak var fourthGoalEnd: UITextField!
#IBOutlet weak var fifthGoaltext: UITextField!
#IBOutlet weak var fifthGoalStart: UITextField!
#IBOutlet weak var fifthGoalEnd: UITextField!
#IBAction func enter(_ sender: Any!) {
let vc1 = ViewController()
vc1.firstGoalLabel.text = firstGoaltext.text
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
firstGoalStart.resignFirstResponder()
}
}
extension SecondViewController : UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
What I am doing wrong here?
Try running the code snippet in “viewDidAppear” instead of “viewDidLoad”

comparing local images swift

"Optional type Bool cannot be used as a boolean; test for !nil instead"
Is the error I'm getting
I'm trying to make a "slot machine" app, very basic,
You press the UIButton, and the three images should all change, randomly, if the 3 matches, print "You won!"
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var img1: UIImageView!
#IBOutlet weak var img2: UIImageView!
#IBOutlet weak var img3: UIImageView!
#IBOutlet weak var rollBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func onRollPress(sender: AnyObject) {
let randomRoll = ImgArray().getRandomImage()
img1.image = randomRoll
img2.image = randomRoll
img3.image = randomRoll
if (img1.image! == img2 && img3) {
print("You won!")
}
}
}
If your images are in an array, why not get the indexes of the images and compare that. Or you could convert the images to base64 strings and compare those.
Edit: Not knowing much about your ImgArray class, this may work for you:
#IBAction func onRollPress(sender: AnyObject) {
let randomRoll1 = ImgArray().getRandomImage()
let randomRoll2 = ImgArray().getRandomImage()
let randomRoll3 = ImgArray().getRandomImage()
img1.image = randomRoll1
img2.image = randomRoll2
img3.image = randomRoll3
let imgIndex1 = ImgArray().indexOf(randomRoll1)
let imgIndex2 = ImgArray().indexOf(randomRoll2)
let imgIndex3 = ImgArray().indexOf(randomRoll3)
if (imgIndex1 == imgIndex2 && imgIndex3) {
print("You won!")
}
}

How can I get hundredths place instead of tenths place in output

When I enter an amount in the text field I get in total the amount in tenths place, so how can I get hundredths place instead of tenths place?
Also how can I get the tip percentage label an integer instead of a decimal?
import UIKit
class ViewController: UIViewController, SettingsDelegate {
//Inputs
#IBOutlet weak var amountTextField: UITextField!
//Labels
#IBOutlet weak var TipPercentageLabel: UILabel!
#IBOutlet weak var numberOfPersonLabel: UILabel!
#IBOutlet weak var tipAmountLabel: UILabel!
#IBOutlet weak var totalBillLabel: UILabel!
#IBOutlet weak var billPerPersonLabel: UILabel!
//Slider & Stepper
#IBOutlet weak var tipSlider: UISlider!
#IBOutlet weak var personsStepper: UIStepper!
//Variables
var tipPercentage : Double = NSUserDefaults.standardUserDefaults().doubleForKey("DefaultTipRate") ?? 0.20
var numberOfPerson:Int = 1
let numberFormatter:NSNumberFormatter = NSNumberFormatter()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tipAmountLabel.text = "$0.00"
totalBillLabel.text = "Bill Total"
billPerPersonLabel.text = "$0.00"
numberOfPersonLabel.text = "1"
self.amountTextField.becomeFirstResponder()
print("DefaultTipRate")
let tipPercentage : Double = NSUserDefaults.standardUserDefaults().doubleForKey("DefaultTipRate")
TipPercentageLabel.text = self.numberFormatter.stringFromNumber(tipPercentage)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupContainer() {
tipSlider.minimumValue = 0
tipSlider.maximumValue = 100
tipSlider.value = 20
tipSlider.addTarget(self, action: "sliderTipChanged:", forControlEvents: .ValueChanged)
personsStepper.minimumValue = 1
personsStepper.maximumValue = 30
personsStepper.value = 1
personsStepper.addTarget(self, action: "sliderPersonChanged:", forControlEvents: .ValueChanged)
amountTextField.text = ""
refreshCalculation()
}
#IBAction func OnEditingFieldBill(sender: AnyObject) {
refreshCalculation()
}
func refreshCalculation() {
numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
if let amount = numberFormatter.numberFromString(amountTextField.text!) as? Double {
let tipAmount = amount * tipPercentage
let totalBill = amount + tipAmount
let billPerPerson = totalBill / Double(numberOfPerson)
numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
tipAmountLabel.text = numberFormatter.stringFromNumber(tipAmount)
totalBillLabel.text = numberFormatter.stringFromNumber(totalBill)
billPerPersonLabel.text = numberFormatter.stringFromNumber(billPerPerson)
} else {
tipAmountLabel.text = "-"
totalBillLabel.text = "-"
billPerPersonLabel.text = "-"
}
numberFormatter.numberStyle = NSNumberFormatterStyle.PercentStyle
numberFormatter.minimumFractionDigits = 2
numberFormatter.maximumFractionDigits = 2
TipPercentageLabel.text = String(format: "%.0f%%", tipPercentage)
numberOfPersonLabel.text = "\(numberOfPerson)"
}
#IBAction func sliderTipChanged(sender: AnyObject) {
tipPercentage = Double(round(tipSlider.value)) / 100
refreshCalculation()
}
#IBAction func StepperPersonChanged(sender: AnyObject) {
numberOfPerson = Int(round(personsStepper.value))
refreshCalculation()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let SettingsViewController = segue.destinationViewController as? SettingsViewController {
SettingsViewController.delegate = self
refreshCalculation()
}
}
func tipPercentageChanged(newValue: Double) {
TipPercentageLabel.text = "\(newValue)%"
tipPercentage = newValue
refreshCalculation()
}
SETTINGS VIEW CODE
import UIKit
protocol SettingsDelegate{
func tipPercentageChanged(newValue : Double)
}
class SettingsViewController: UIViewController {
#IBOutlet weak var tipControl: UISegmentedControl!
var tipRates:Double?
var destName : String!
var delegate :SettingsDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func changeValue(sender: UISegmentedControl) {
var tipRate = [0.05, 0.10, 0.15, 0.20, 0.25, 0.30]
tipRates = (tipRate[tipControl.selectedSegmentIndex])
delegate?.tipPercentageChanged(tipRates!); print("(tipRates)")
NSUserDefaults.standardUserDefaults().setDouble(tipRates!, forKey: "DefaultTipRate")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
Since you are using NSNumberFormatter, set maximumFractionDigits and minimumFractionDigits properties to 2:
let numberFormatter = NSNumberFormatter()
numberFormatter.maximumFractionDigits = 2
numberFormatter.minimumFractionDigits = 2
let str = numberFormatter.stringFromNumber(14.7) // "14.70"
Alternatively, you could use the String(format:) constructor:
let str = String(format: "%.2f", 14.7) // "14.70"
For your tip percentage, since you are storing it as a decimal percentage, you can do:
let tipPercentage: Double = 0.17
TipPercentageLabel.text = String(format: "%.0f%%", tipPercentage * 100) // "17%"

How to use UIStepper to put integer in to a text field with swift

How Can I use Swift to put integer in textfield from UIStepper?
this is how I did it in Objective C:
- (IBAction)oneClicker:(UIStepper *)sender {
self.oneValue.text = [NSString stringWithFormat:#"%d",
[[NSNumber numberWithDouble:[(UIStepper *)sender value]] intValue]];
AudioServicesPlaySystemSound(_PlaySound);
}
It's simple
#IBOutlet weak var oneValue: UITextField!
#IBAction func oneClicker(sender: UIStepper) {
self.oneValue.text = Int(sender.value).description
}
Here is how I got it to work don't know if the best way but here it is
#IBOutlet weak var oneClicker: UIStepper!
#IBAction func oneClicker(sender: UIStepper) {
oneValue.text = "\(Int(oneClicker.value))"
}
While trying above, got an error. Tried something different and it worked.
#IBOutlet var quantity: UILabel!
#IBOutlet var StepCounter: UIStepper!
override func viewDidLoad() {
super.viewDidLoad()
StepCounter.autorepeat = true
StepCounter.maximumValue = 10.0
StepCounter.minimumValue = 1.0
println(StepCounter.value)
quantity.text = "\(Int(StepCounter.value))"
StepCounter.addTarget(self, action: "stepperValueDidChange:", forControlEvents: .ValueChanged)
}
func stepperValueDidChange(stepper: UIStepper) {
let stepperMapping: [UIStepper: UILabel] = [StepCounter: quantity]
stepperMapping[stepper]!.text = "\(Int(stepper.value))"
}