How do I access a variable in a button action in Swift - ios

I cannot access the variable incomeValue in the savingsGoal function. Xcode gives me the error "Use of unresolved identifier 'incomeValue'.
#IBAction func incomeSliderChanged(sender: UISlider) {
var incomeValue = Double(sender.value)
currentIncomeLabel.text = ("$\(incomeValue) /yr")
}
#IBAction func savingsSliderChanged(sender: UISlider) {
var savingsValue = Int(sender.value)
savingsLabel.text = ("\(savingsValue)% of income")
println("savings value \(savingsValue)%")
}
#IBAction func indexChanged(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
println("first segement clicked")
case 1:
println("second segment clicked")
default:
break;
}
}
#IBAction func calculateButtonPressed(sender: AnyObject) {
}
func savingsGoal () {
var futureIncome = incomeValue + (incomeValue * 3.8)
}
}

Your problem is that you declared incomeValue inside your incomeSliderChanged(_:) function. This limits the scope of incomeValue to that function, meaning you can only reference it from withing the opening { and closing } of incomeSliderChange(_:). To fix this declare your incomeValue variable outside of the function.
var incomeValue: Double = 0.0 // You can replace 0.0 with the default value of your slider
#IBAction func incomeSliderChanged(sender: UISlider) {
// Make sure you get rid of the var keyword.
// The use of var inside this function would create a
// second incomeValue variable with its scope limited to this function
// (if you were to do this you could reference the other incomeValue
// variable with self.incomeValue).
incomeValue = Double(sender.value)
currentIncomeLabel.text = ("$\(incomeValue) /yr")
}
func savingsGoal() {
// You can now access incomeValue within your savingsGoal() function
var futureIncome = incomeValue + (incomeValue * 3.8)
}
If you are new to programming, I recommend reading about the concept of Scope: http://en.wikipedia.org/wiki/Scope_(computer_science)

Related

ios Swift Protocol Data

I don't use storyboards.
I want to send protocol data using #objc button action.
However, the sent view controller does not run the protocol function.
May I know what the reason is?
In fact, there's a lot more code.
Others work, but only protocol functions are not executed.
The didUpdataChampion function is
Data imported into a different protocol.
I have confirmed that there is no problem with this.
protocol MyProtocolData {
func protocolData(dataSent: String)
func protocolCount(dataInt: Int)
}
class PickViewController: UIViewController,ChampionManagerDelegate{
static let identifier = "PickViewController"
var count = 0
var urlArray = [URL]()
var pickDelegate : MyProtocolData?
override func viewDidLoad() {
super.viewDidLoad()
champions.riot(url: "myURL")
}
#objc func topHand(){
pickDelegate?.protocolData(dataSent: "top")
print(count)
pickDelegate?.protocoCount(dataInt: count)
let cham = ChampViewController()
cham.modalPresentationStyle = .fullScreen
present(cham, animated: true, completion: nil)
}
//Data imported to another protocol
func didUpdataChampion(_ championManager: ChampionManager, champion: [ChampionRiot]) {
print(#function)
count = champion.count
for data in champion {
let id = data.id
guard let url = URL(string: "https://ddragon.leagueoflegends.com/cdn/11.16.1/img/champion/\(id).png") else { return }
urlArray.append(url)
count = urlArray.count
}
}
func didFailWithError(error: Error) {
print(error)
}
}
class ChampViewController: UIViewController,MyProtocolData {
var pickData = ""
var arrayCount = 0
override func viewDidLoad() {
super.viewDidLoad()
}
func protocolData(dataSent: String) {
print(#function)
pickData = dataSent
print(pickData)
}
func protocoCount(dataInt: Int) {
print(#function)
arrayCount = dataInt
print(arrayCount)
}
}
i don't see full code, for instance how you call bind to topHand(), my advice is:
check that topHand - is called
check that pickDelegate isn't nil inside topHand
Create Object fo your PickViewController class and set its delegate to self.
var yourObj = PickViewController()
override func viewDidLoad() {
super.viewDidLoad()
yourObj.delegate = self
}

Why protocol type never gets a value?

I am trying to understand more protocols. I could not figure out myProtocolFunction never call and print or passing the variable as below.
I think my problem is about initialization. When I try with two viewcontroller everything is okay but MyStruct protocol instance is nil. Thanks for your help.
class ViewController: UIViewController, MyProtocol {
var myProtocolValue: String = ""
var globalInstance = "a"
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func click(_ sender: Any) {
var myStruct = MyStruct()
myStruct.myProtocol = self
}
func myProtocolFunction(passing: String) {
globalInstance = passing
print("never print")
}
}
protocol MyProtocol {
func myProtocolFunction(passing: String)
}
struct MyStruct {
var myProtocol: MyProtocol?
init() {
makeSomething()
}
func makeSomething() {
myProtocol?.myProtocolFunction(passing: "abc")
}
}
1- You need to make
var myStruct = MyStruct() // an instance variable
#IBAction func click(_ sender: Any) {
myStruct.myProtocol = self
}
2- Also you call init before even you set myProtocol as its called when you do var myStruct = MyStruct() and at that time myProtocol is nil as its not yet set
init() {
makeSomething()
}
Check full working edit
class ViewController: UIViewController, MyProtocol {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func myProtocolFunction(passing: String) {
print(passing)
}
#IBAction func click(_ sender: Any) {
var myStruct = MyStruct(self)
}
}
protocol MyProtocol {
func myProtocolFunction(passing: String)
}
struct MyStruct {
var myProtocol: MyProtocol?
init(_ mine:MyProtocol) {
myProtocol = mine
makeSomething()
}
func makeSomething() {
myProtocol?.myProtocolFunction(passing: "abc")
}
}
Think about protocols as a type, in your struct you are basically saying
that this struct have a variable of this type ( your protocol )
and on init you are trying to call its function.
What you're missing is setting an instance of type ( your protocol )
so it can get called.
for instance :
MyStruct = MyStruct(myProtocol: ViewController())
Now your nullable protocol have a value and can call it's function in another word, protocols can't have implementation directly into them they're more like a signature contract
Read more about protocols here.
You need to create MyStruct() object out of the click action else when the scope is over your object is deinitialize.
Also, You have to call .makeSomething() function on the button click as the time of object creation delegate is nil.
var myStruct = MyStruct() // Create an instance here
#IBAction func click(_ sender: Any) {
myStruct.myProtocol = self
// Add your action
myStruct.makeSomething()
}

How do I store data (user input from a textfield)

I am using Swift and I want to know how I can store user input as a variable (it’s a double).
I'm still in the learning states so I have been watching youtube tutorials on the situation but nothing helped.
My code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var userInput: UITextField!
override func viewDidLoad() {
userInput.delegate = self
}
#IBAction func Increment(_ sender: UIButton) {
var inc = 0
userInput = userInput + inc
}
#IBAction func Decrement(_ sender: UIButton) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
userInput.resignFirstResponder()
}
}
extension ViewController: UITextFieldDelegate{
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
The user will be able to enter a number and increment or decrement the number by a certain input value.
//fetch any number from textfield
func getValueFromTextfield() -> Double?{
guard let text = userInput.text else {
print("Missing user input")
return nil
}
guard let doubleValue = Double(text) else {
print("parse failure")
return nil
}
return doubleValue
}
// Now for increment and decrement we have methods be like, Am assuming certain input value as 1 to be used for increment and decrement replace this if needed
func increment(){
// get value
if let value = getValueFromTextfield(){
userInput.text = “\(value + 1)” // increment by 1
}
}
func decrement(){
// get value and check if it’s greater than zero
if let value = getValueFromTextfield(), value > 0{
userInput.text = “\(value - 1)” // decrement by 1
}
}
#IBAction func Increment(_ sender: UIButton) {
increment()
}
#IBAction func Decrement(_ sender: UIButton) {
decrement()
}
These method will help you achieve increment or decrement operation without need to store value in any variable.
If you still want to save value in variable just simply store value returned from method let valueToStore = getValueFromTextfield()
Your code won't compile correctly but the answer to your question is:
let doubleValue = Double(userInput.text!)! converts your code to double
or better using optional unwrapping:
guard let text = userInput.text else {
print("text of userInput is nil")
return
}
guard let doubleValue = Double(text) else {
print("Impossible to parse \(text) into Double")
return
}
print(doubleValue)
#IBAction func Increment(_ sender: UIButton) {
if let text = userInput.text, var doubleText = Double(text) {
doubleText = doubleText + 1
userInput.text = "\(doubleText)"
}
}
Similarly you can write for Decrement.
#IBAction func Increment(_ sender: UIButton) {
var inc = 0
userInput.text = ( Double(userInput.text) + Double(inc) ).rounded(toPlaces: 1)
}

UIButton inside UISegmentedControl action

I am continuing my calculation program to improve my skills in Swift code. Right now I have a problem: I want that an UISegmentedControl select the operator of my operations (+, - ecc..) and when one is selected a UIButton func calculate the values based on the decision of the UISegmentedControl.
Here is the code but is not working.
Thanks,
Matteo
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var firstNumber: UITextField!
#IBOutlet weak var secondNumber: UITextField!
#IBOutlet weak var resultButton: UIButton!
#IBOutlet weak var resultNumber: UILabel!
#IBOutlet weak var operatorSelector: UISegmentedControl!
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 operatorSelectorChanged(_ sender: UISegmentedControl) {
switch operatorSelector.selectedSegmentIndex {
case 0:
#IBAction func resultFunction(_ sender: AnyObject) {
if let firstNumberConv :Int = Int(firstNumber.text!), let secondNumberConv :Int = Int(secondNumber.text!) {
let result = firstNumberConv + secondNumberConv
resultNumber.text = "\(result)"
} else { resultNumber.text = "Inserire solo valori numerici"}
}
case 1:
#IBAction func resultFunction(_ sender: AnyObject) {
if let firstNumberConv :Int = Int(firstNumber.text!), let secondNumberConv :Int = Int(secondNumber.text!) {
let result = firstNumberConv - secondNumberConv
resultNumber.text = "\(result)"
} else { resultNumber.text = "Inserire solo valori numerici"}
}
default:
break;
}
}
}
Try removing the lines with #IBAction func ... inside your switch cases.
I think your #IBAction func operatorSelectorChanged should look something like this:
#IBAction func operatorSelectorChanged(_ sender: UISegmentedControl) {
switch operatorSelector.selectedSegmentIndex {
case 0:
if let firstNumberConv = Int(firstNumber.text!), let secondNumberConv = Int(secondNumber.text!) {
let result = firstNumberConv + secondNumberConv
resultNumber.text = "\(result)"
} else { resultNumber.text = "Inserire solo valori numerici"}
case 1:
if let firstNumberConv = Int(firstNumber.text!), let secondNumberConv = Int(secondNumber.text!) {
let result = firstNumberConv - secondNumberConv
resultNumber.text = "\(result)"
} else { resultNumber.text = "Inserire solo valori numerici"}
default:
break;
}
}
A possible solution for your problem is to define an IBAction that calculates the result of adding/subtracting two numbers
#IBAction func calculate(_ sender: AnyObject) {
if let a = Int(firstNumber.text!), let b = IntsecondNumber.text!) {
switch operatorSelector.selectedSegmentIndex {
case 0:
resultNumber.text = "\(a+b)"
case 1:
resultNumber.text = "\(a-b)"
default:
print("❗️unknown operator selected")
}
}
}
You could then bind this action to the sent events from your user interface: for example the Editing Changed event of your text fields (firstNumber and secondNumber) and the Value Changed of your segmented control (operatorSelector)
I created an example project that illustrates this: https://github.com/dev1an/calculator
How to bind multiple events to one IBAction
Write down the IBAction in code (like the calculate action I wrote above). Go to your storyboard and open the assistent editor (AltCmdEnter). Select a UI element (like a text field) in the interface builder. Open the Connections Inspector (AltCmd6) and drag from the circle next to a sent event (for example Editing Changed) to your IBAction code.

How to make calculator calculate in decimal form

Here's my code for my calculator and it works fine!
import UIKit
class ViewController: UIViewController {
var number1 = 0
var number2 = 0
var operation = 0
#IBOutlet var screen: UILabel!
#IBAction func Onebutton(sender: AnyObject) {
addNumber(1)
}
#IBAction func Twobutton(sender: AnyObject) {
addNumber(2)
}
#IBAction func Threebutton(sender: AnyObject) {
addNumber(3)
}
#IBAction func Fourbutton(sender: AnyObject) {
addNumber(4)
}
#IBAction func Fivebutton(sender: AnyObject) {
addNumber(5)
}
#IBAction func Sixbutton(sender: AnyObject) {
addNumber(6)
}
#IBAction func Sevenbutton(sender: AnyObject) {
addNumber(7)
}
#IBAction func Eightbutton(sender: AnyObject) {
addNumber(8)
}
#IBAction func Ninebutton(sender: AnyObject) {
addNumber(9)
}
#IBAction func Zerobutton(sender: AnyObject) {
addNumber(0)
}
#IBAction func Multiplybutton(sender: AnyObject) {
operation = 1
}
#IBAction func Dividebutton(sender: AnyObject) {
operation = 2
}
#IBAction func Addbutton(sender: AnyObject) {
operation = 3
}
#IBAction func Subtractbutton(sender: AnyObject) {
operation = 4
}
#IBAction func Equalsbutton(sender: AnyObject) {
switch operation{
case 1: screen.text = String (number1*number2)
case 2: screen.text = String (number1/number2)
case 3: screen.text = String (number1+number2)
case 4: screen.text = String (number1-number2)
default: println()
}
}
#IBAction func clearbutton(sender: AnyObject) {
number1 = 0
number2 = 0
operation = 0
screen.text = "0"
}
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.
}
func addNumber (pushButton : Int){
if operation == 0 {
number1 = number1*10+pushButton
screen.text = String (number1)
} else {
number2 = number2*10+pushButton
screen.text = String (number2)
}
}
}
But I want to make the calculator calculate in decimal form and not round off to the nearest number.
Use floats.
var number: Float = 0
number = number + 0.1
println(number)
//0.1 should be printed.
You are currently basically saying:
var number: Int = 0
This is pretty much how the computer reads it; number is an integer. To make it so that number can be a decimal (float), you have to say:
var number: Float = 0

Resources