Counting Up and Down using Volume buttons on iOS (Swift) - ios

Hi I creating an app for myself, where I want to count and display the # on the screen. I want to use the volume buttons to count up and down. I was able create a button on screen to count up and down but I want to use the physical buttons. I have listed what I have so far, but the volume buttons doesn't seem to work. I've replaced AVAudioSession with AVAudioPlayer hoping to control the volume with the slider. I get a error EXC_BAD_ACCESS (Code=1, Adress=0x48)
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
#IBOutlet weak var counter: UILabel!
#IBOutlet weak var tapCounterUp: UIButton!
#IBOutlet weak var tapCounterDown: UIButton!
#IBOutlet weak var tapReset: UIButton!
#IBOutlet weak var volumeController: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
//Starts the count at 0
var count : Int = 0
//Adds +1 to Count
#IBAction func buttonUp(_ sender: Any) {
count += 1
counter.text = String(count)
}
//Subtracts -1 to Count
#IBAction func buttonDown(_ sender: Any) {
count -= 1
counter.text = String(count)
}
//Resets the Count to "0"
#IBAction func buttonReset(_ sender: Any) {
count = 0
counter.text = String(count)
}
//Volume Controller
#IBAction func volumeControl(_ sender: UISlider) {
let sliderValue = lroundf(sender.value)
counter.text = "\(sliderValue)"
/// **This is were the Error occurs.**
audioPlayer.volume = volumeController.value
}
// End of function, don't delete
}

Related

Switching between two strings after button is pressed

So I am working on a BlackJack game for iOS using Swift. I have two buttons, HIT and STAY. Here is where my problem lies: When I press the originally, it is player 1's turn. But after clicking the HIT button, I want the turn label to oscillate between player 2 and player 1. So after player 1 clicks HIT button, I want the turn label to read player 2 and then player 1. Here is what I got so far:
class ViewController: UIViewController {
var deck = PlayingCardDeck()
#IBOutlet weak var cardLabel: UILabel!
#IBOutlet weak var playerTurn: UILabel!
#IBOutlet weak var scorePlayerOne: UILabel!
#IBOutlet weak var scorePlayerTwo: UILabel!
#IBAction func btnHit(_ sender: Any) {
cardLabel.text = String(describing: deck.drawCard()!)
playerTurn.text = String(describing: "Player 2")
}
#IBAction func btnStay(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
deck.shuffle()
}
}
With the method I have, it mimics what I want to happen (switches to player 2)
You need a variable to track which player is currently playing and then change the label based on those variable value.
var isFirstPlayerTurn: Bool = true
#IBAction func btnHit(_ sender: Any) {
cardLabel.text = String(describing: deck.drawCard()!)
isFirstPlayerTurn = !isFirstPlayerTurn
playerTurn.text = isFirstPlayerTurn ? "Player 1" : "Player 2"
}
Create two labels, one for each player. Then hide player 2's label and flip it while hidden in viewDidLoad(). Once the turn changes, flip both labels while simultaneously showing and hiding the labels based who's turn it is.
To flip the label, use CGAffineTransform. Use the labels' alpha property to show and hide the labels.
func changeTurn(_ player: Int) {
UIView.animate(withDuration: 0.5) {
playerTurn1.transform = CGAffineTransform(scaleX: -playerTurn1.transform.a, y: playerTurn1.transform.d)
playerTurn2.transform = CGAffineTransform(scaleX: -playerTurn2.transform.a, y: playerTurn2.transform.d)
playerTurn1.alpha = player == 1 ? 1 : 0
playerTurn2.alpha = player == 2 ? 1 : 0
}
}
Usage:
#IBOutlet weak var playerTurn1: UILabel!
#IBOutlet weak var playerTurn2: UILabel!
private var turn = 1
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
deck.shuffle()
playerTurn2.alpha = 0
playerTurn2.transform = CGAffineTransform(scaleX: -playerTurn2.transform.a, y: playerTurn2.transform.d)
}
#IBAction func btnHit(_ sender: Any) {
cardLabel.text = String(describing: deck.drawCard()!)
turn = turn == 1 ? 2 : 1
changeTurn(turn)
}
Make sure both labels are the same frames.

why my stepper does't give the correct value when I tap the increment button?

I am using kw stepper pod, since it is customizable. I can separate the increment button, decrement button and using my own label. but the behaviour should be the same as UIStepper
that is what it looks like, it consists of 1 increment button, 1 decrement button and counter label.
here is the code on my view controller:
import UIKit
import KWStepper
class ViewController: UIViewController {
#IBOutlet weak var counterLabel: UILabel!
#IBOutlet weak var decrementButton: UIButton!
#IBOutlet weak var incrementButton: UIButton!
var stepper: KWStepper!
override func viewDidLoad() {
super.viewDidLoad()
stepper = KWStepper(decrementButton: decrementButton, incrementButton: incrementButton)
stepper.autoRepeat = false
stepper.autoRepeatInterval = 1
stepper.wraps = false
stepper.minimumValue = 0
stepper.maximumValue = 100
stepper.incrementStepValue = 1
stepper.decrementStepValue = 1
stepper.value = 0.0
counterLabel.text = "\(stepper.value)"
}
#IBAction func incrementButtonDidTapped(_ sender: Any) {
counterLabel.text = "\(stepper.value)"
}
#IBAction func decrementButtonDidTapped(_ sender: Any) {
counterLabel.text = "\(stepper.value)"
}
}
I connect the increment and decrement button using #IBAction touch up inside event.
so I expect when I tap the increment button, it will increase from
0,0 -> 1.0 -> 2.0 -> 3.0 and so on.
but in my case, when tap the increment button it will give
0,0 -> 0,0 -> 1,0 -> 2,0
the 0,0 will appear twice. why it appears twice ? how to solve this issue
I know that I can see the stepper value from value change event like this
stepper
.valueChanged { stepper in
// ...
}
but I need to separate the event from increment and decrement button
here is the project on my google drive: https://drive.google.com/file/d/1IgeVW1OemRttoAOqJ6Ba8LpyZC_rc3-o/view?usp=sharing
The incrementButtonDidTapped and decrementButtonDidTapped methods are possibly being called before stepper.value changes, since KWStepper also listens for touchUpInside events from both of these buttons to change its value.
KWStepper exposes two properties decrementCallback and incrementCallback which you can use to get notified when the value gets decremented/incremented. You can use these instead of an IBAction on the two buttons.
stepper.decrementCallback = { (stepper) in
self.counterLabel.text = "\(stepper.value)"
}
stepper.incrementCallback = { (stepper) in
self.counterLabel.text = "\(stepper.value)"
}
Alternatively, you can confirm to KWStepperDelegate and implement KWStepperDidIncrement and KWStepperDidDecrement delegate methods to get notified.
import UIKit
import KWStepper
class ViewController: UIViewController, KWStepperDelegate {
#IBOutlet weak var counterLabel: UILabel!
#IBOutlet weak var decrementButton: UIButton!
#IBOutlet weak var incrementButton: UIButton!
var stepper: KWStepper!
override func viewDidLoad() {
super.viewDidLoad()
stepper = KWStepper(decrementButton: decrementButton, incrementButton: incrementButton)
stepper.autoRepeat = false
stepper.autoRepeatInterval = 1
stepper.wraps = false
stepper.minimumValue = 0
stepper.maximumValue = 100
stepper.incrementStepValue = 1
stepper.decrementStepValue = 1
stepper.value = 0.0
// Set the delegate
stepper.delegate = self
counterLabel.text = "\(stepper.value)"
}
#objc func KWStepperDidIncrement() {
counterLabel.text = "\(stepper.value)"
}
#objc func KWStepperDidDecrement() {
counterLabel.text = "\(stepper.value)"
}
}
You can replace your click events with following code
#IBAction func incrementButtonDidTapped(_ sender: Any) {
stepper.valueChanged { (steper) in
self.counterLabel.text = "\(steper.value)"
}
}
#IBAction func decrementButtonDidTapped(_ sender: Any) {
stepper.valueChanged { (steper) in
self.counterLabel.text = "\(steper.value)"
}
}

How can I increment a label by pressing a button that is in a separate view?

so basically I'm familiar with app development and Xcode, but I'm still in the beginning stages of learning and I need some help. I've created a emotions quiz type UI and at the end of the 10 questions, I have a page that displays the different emotions and the scores that the user earned throughout the quiz. What I need help on is wen the user clicks a button on question 1 to get the label on my results page to increase by 1. I've tried many different methods so far but can't seem to quite figure it out. Ive linked my buttons to their respective view controller as actions and the labels to their respective view controller as outlets.
import UIKit
class Question1: UIViewController {
#IBAction func buttonlightgreen(_ sender: UIButton) {
print ("light green")
sadscoreText += 1
}
#IBAction func buttonred(_ sender: Any) {
print ("red")
angryscoreText += 2
happyscoreText += 1
}
#IBAction func buttonpurple(_ sender: Any) {
print ("purple")
annoyedscoreText += 1
stressedscoreText += 1
}
#IBAction func buttondarkgreen(_ sender: Any) {
print ("dark green")
relaxedscoreText += 2
tiredscoreText += 1
}
#IBAction func buttonyellow(_ sender: Any) {
print ("yellow")
happyscoreText += 1
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
That is the code for the buttons and this is the code for the labels.
import UIKit
var sadscoreText = 0
var happyscoreText = 0
var relaxedscoreText = 0
var angryscoreText = 0
var annoyedscoreText = 0
var tiredscoreText = 0
var stressedscoreText = 0
class Results: UIViewController {
#IBOutlet weak var sadscore: UILabel!
#IBOutlet weak var happyscore: UILabel!
#IBOutlet weak var relaxedscore: UILabel!
#IBOutlet weak var angryscore: UILabel!
#IBOutlet weak var annoyedscore: UILabel!
#IBOutlet weak var tiredscore: UILabel!
#IBOutlet weak var stressedscore: UILabel!
var sadscoreText: Int = 0 {
didSet {
sadscore.text = "\(sadscoreText)"
}
}
override func viewDidLoad() {
super.viewDidLoad()
sadscoreText = 0
happyscoreText = 0
relaxedscoreText = 0
angryscoreText = 0
annoyedscoreText = 0
tiredscoreText = 0
stressedscoreText = 0
}
}
I believe the reason its not working is because you are assigning 0 to the values before assigning the modified values to label in viewDidLoad method. You can achieve the required behaviour like this:
Modify your Results view controller as follows:
import UIKit
var sadscoreText = 0
var happyscoreText = 0
var relaxedscoreText = 0
var angryscoreText = 0
var annoyedscoreText = 0
var tiredscoreText = 0
var stressedscoreText = 0
class Results: UIViewController {
#IBOutlet weak var sadscore: UILabel!
#IBOutlet weak var happyscore: UILabel!
#IBOutlet weak var relaxedscore: UILabel!
#IBOutlet weak var angryscore: UILabel!
#IBOutlet weak var annoyedscore: UILabel!
#IBOutlet weak var tiredscore: UILabel!
#IBOutlet weak var stressedscore: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
sadscore.text = "\(sadscoreText)"
happyscore.text = "\(happyscoreText)"
//follow the same for other labels
//you can set the values again to zero after showing the labels on the screen like this
sadscoreText = 0
happyscoreText = 0
}
}

Accessing variables in other ViewControllers Swift 3

I have a problem I can't seem to solve myself, I have two view controllers, the first one contains three variables that stores integers. On my second view controller I have 3 sliders which manipulates a label under each slider with a number.
I want the numbers from these 3 sliders to replace the numbers that were set in the three variables on my first view controller when I click a button on the second view controller but when I when I type in the variable name it doesn't show up in the second view controller?
Can somebody explain what I may be doing wrong as I thought the variables were public and globally accessible throughout my app but I'm struggling to figure out what I'm doing wrong.
Here is some of my code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var timer = Timer()
var softTime = 180
var mediumTime = 300
var hardTime = 600
var chosenTime = 0
I want softTime, mediumTime & hardTime to be changed from the button in the next view controller:
import UIKit
class SettingsViewController: UIViewController {
#IBOutlet weak var softLabel: UILabel!
#IBOutlet weak var softSliderValue: UISlider!
#IBAction func softSlider(_ sender: Any) {
let currentValue = Int(softSliderValue.value)
softLabel.text = "\(currentValue)"
}
#IBOutlet weak var mediumLabel: UILabel!
#IBOutlet weak var mediumSliderValue: UISlider!
#IBAction func mediumSlider(_ sender: Any) {
let currentValue = Int(mediumSliderValue.value)
mediumLabel.text = "\(currentValue)"
}
#IBOutlet weak var hardLabel: UILabel!
#IBOutlet weak var hardSliderValue: UISlider!
#IBAction func hardSlider(_ sender: Any) {
let currentValue = Int(hardSliderValue.value)
hardLabel.text = "\(currentValue)"
}
#IBAction func setTimesButton(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
//in Second VC
protocol PassDataDelegte: class {
func your method(first: String, second: String, third: String)
}
weak var delegate: PassDataDelegte?
func youction button() {
delegate?.yourmethod(first, timeString: second, third: date)
}
// in First VC
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DeadlineSegue" {
let dvc = segue.destinationViewController as! YourSecondViewController
dvc.delegate = self
}
}
extension YourFirstViewController: PassDataDelegte {
func sendDateTime((first: String, second: String, third: String) {
print(first)
print(second)
print(third)
}

Add the value of multiple sliders in swift then average them?

Im doing this wrong I but I'm not sure how to get it I could really use some help. I have 3 sliders (I may need more later) and basically they are 1-10 in value kinda for a rating system and i want them averaged to create an average score.. so this is what I have
#IBOutlet weak var speed: UISlider!
#IBAction func speedChange(sender: AnyObject) {
let speedValue = speed.value
}
#IBOutlet weak var body: UISlider!
#IBAction func bodyChange(sender: AnyObject) {
let bodyValue = body.value
}
#IBOutlet weak var details: UISlider!
#IBAction func detailsChange(sender: AnyObject) {
let detailsValue = details.value
}
#IBOutlet weak var score: UILabel!
func final() {
var thescore = (speed.value + body.value + details.value) / 3
score.text = "\(thescore)"
}
Only problem is it doesn't work. the + errors out, so I need to fix that, but even still i think my methodology is completely off.
It worked for me. Are you sure the outlets in the storyboard are linked to your Controller ?
Also, you may want to call your function final every time a slider changed its value, like this :
#IBOutlet weak var sliderA: UISlider!
#IBAction func sliderAchanged(sender: AnyObject) {
fonction()
}
#IBOutlet weak var sliderB: UISlider!
#IBAction func sliderBchanged(sender: AnyObject) {
fonction()
}
#IBOutlet weak var sliderC: UISlider!
#IBAction func sliderCchanged(sender: AnyObject) {
fonction()
}
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
fonction()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func fonction() {
var thescore = (sliderA.value + sliderB.value + sliderC.value ) / 3
label.text = "\(thescore)"
}​
And I added a call to the function in viewDidLoad method to initilaize the label's text.

Resources