I was scouring the web for blogs and videos about programming in Swift I found a couple that were showing how to build a calculator. I decided to build one of my own to help me in my swift discovering journey.

If you need the Xcode project files you can download them here.

##How it works

It’s a basic calculator, nothing fancy.  The app performs the usual arithmetic operations plus a series specialized percentage buttons intended to be used as tip calculators. I personally tested it on my iPhone 5 and it works as intended.

Fig 1a   image

I created the following user stories to guide me through the development:

  1. I need to be able to perform the basic arithmetic operations +,-,* and /
  2. I need to be able to perform operations with non integer numbers
  3. As a  user every time I hit the = sign the operation is performed and the result is shown on the display
  4. As a user I need to be able to perform an operation on a result displayed
  5. I need to be able to clear the screen without clear the memory
  6. I need to be able to clear the memory
  7. As a user I need to have specialized "tip" calculator button at 10%, 15%, 18%, and 20%.
    1. When I hit those button the resulting percentage in shown on the screen
    2. Every percentage needs to perform an independent calculation

 

Creating the app in XCode 6

As in every iOS application we need to start in Xcode 6 as a brand new application: Fig.2

  1. Select a single view application
  2. In the following screen select "Swift" as a language
  3. We do not need "core data" so leave it uncheck
  4. To keep it simple I made the app for iPhone only

The Storyboard

I kept the calculator’s look and feel is very simple (see Fig. 3). I created all the numbers buttons, the Clear and All Clear buttons, and all the standard arithmetic operations plus additional specialized “tip” buttons.

Fig.3

  • The digits 0-9 and the decimal (.) are connected to the IBAction "digitTapped"
  • The buttons AC  is connected to theIBAction "allClearTapped"
  • The buttons C  is connected to the IBAction "clearScreenTapped"
  • The operands buttons +, -, x, and / are connected to the IBAction "operationTapped"
  • The buttons with 10%, 15%, 18% and 20% are connected to the IBAction "percentageTapped"
  • The equal (=) button is connected to the IBAction "equalTapped"

The way I organized the layout is explained in Fig.4  and is as follows:

Fig.4

  • (1) Is the main label which is named answerFieldLabel.  The results are displayed here
  • (2) This is a hidden label named operandLabel in which keeps track of the operand the user has chosen at any given time (+,-,x, /)
  • (3) All Clear and Clear buttons. The AC resets all the variables and arrays, the C only resets the answerFieldLabel
  • (4) This is the percentage or "tip" button and performs a percentage calculation based on the result saved
  • (5) The operations buttons: addition, subtraction, multiplication and division
  • (6) The equal button that performs the operations
  • (7) The keypad including the decimal dot (.)

##The Classes I create two classes for this project: ArithmeticOperation and tipCalculator.

The main class for the Calculator is the ArithmeticOperation class which returns the value of the operation requested. Each operation is a method (addition, subtraction, multiplication and division).

All the methods are pretty straight forward. For the division() method I implemented a failsafe to avoid a division by zero operation.

ArithmeticOperation  {
    let righNumber: Double
    let leftNumber: Double
    
    init(righNumber: Double, leftNumber: Double) {
        self.righNumber = righNumber
        self.leftNumber = leftNumber
    }
    
    func addition() -> Double {
        result = righNumber + leftNumber
        return result
    }
    
    func subtraction() -> Double {
        return righNumber - leftNumber
    }
    
    func multiplication() -> Double {
        return righNumber * leftNumber
    }
    
    func division() -> Double {
        if leftNumber.isZero == false {
            return righNumber / leftNumber
        } else {
            return 0.0
        }
        
    }
}

For the percentage or “tip” calculator I created a separate class called tipCalculator class that has a method called calculatedTip()  that returns the percentage chosen.

let total: Double
    let tipPerc: Double
    
    init(total:Double, tipPerc: Double) {
        self.total = total
        self.tipPerc = tipPerc
    }
    
    func calculatedTip() -> Double {
        return total * tipPerc
        
    }

You can try out all the classes by cutting and pasting the code in the Xcode playground:

##The Code The four most important functions are digitTapped(),  percentageTapped()equalTapped(), and operatorTapped(). I use an array called resultArray to keep track of the result. Also I have two variables rNumber and lNumber with the values of the right and left numbers that are needed for an arithmetic operation as in ”rNumber + lNumber = result”. The variable “op” represent the arithmetic operand chosen and it’s connected to operandLabel

var resultArray: Array = []
var rNumber: NSString = ""
var lNumber: NSString = ""
var op: String = ""
var result: Double = 0.0

This is the code in the ViewController.swift file between the brackets under “class ViewController: UIViewController”:

@IBOutlet var operandLabel: UILabel!
    
    @IBAction func allClearTapped(sender: UIButton) {
        answerFieldLabel.text = "0.0"
        operandLabel.text = ""
        resultArray.removeAll()
    }

    @IBAction func clearScreenTapped(sender: AnyObject) {
        answerFieldLabel.text = "0.0"
    }
    
    @IBAction func digitTapped(theDigit: UIButton) {
        var digit = theDigit.titleLabel?.text
        if answerFieldLabel.text == "" || answerFieldLabel.text == "0.0" 
        || answerFieldLabel.text == "0.00"
        {
            answerFieldLabel.text = digit
        } else {
            answerFieldLabel.text = answerFieldLabel.text! + digit!
        }
    }
    
    @IBAction func percentageTapped(tipButton: UIButton) {
        var tipDefault: Dictionary = ["10%": 0.1, "15%": 0.15, "18%": 0.18, "20%": 0.2]
        var tip: Double = 0.0
        var numberInScreen: NSString = answerFieldLabel.text!
        
        for (key, value) in tipDefault {
            if tipButton.titleLabel?.text == key {
                tip = value
            }
        }

        resultArray.append(numberInScreen.doubleValue)
        var result = tipCalculator(total: resultArray[0].doubleValue, tipPerc: tip)
        var totalTip = result.calculatedTip()
        answerFieldLabel.text = String(format:"%.02f", totalTip)

    }
    
    @IBAction func equalTapped(sender: AnyObject?) {

        var rightNum: Double
        var leftNum: Double
        var lNumber: NSString = ""
        
        rightNum = rNumber.doubleValue
        lNumber = answerFieldLabel.text! as NSString //Necessary to convert to Double
        leftNum = lNumber.doubleValue
        
        var answer = ArithmeticOperation(righNumber: rightNum, leftNumber: leftNum)
        if op == "+" {
            answerFieldLabel.text = String(format:"%.02f", answer.addition())
            operandLabel.text = ""
        } else if op == "-" {
            answerFieldLabel.text = String(format:"%.02f", answer.subtraction())
            operandLabel.text = ""
        } else if op == "x" {
            answerFieldLabel.text = String(format:"%.02f", answer.multiplication())
            operandLabel.text = ""
        } else if op == "/" {
            answerFieldLabel.text = String(format:"%.02f", answer.division())
            operandLabel.text = ""
        }else {
            answerFieldLabel.text = "Operation Error!"
        }
    }
    
    @IBAction func operationTapped(sender: UIButton) {
        
        if operandLabel.text == "" {
            rNumber = answerFieldLabel.text!
            operandLabel.text = sender.titleLabel?.text
            op = operandLabel.text!
            answerFieldLabel.text = "0.0"
        } else {
            answerFieldLabel.text = "0.0"
            equalTapped(nil)            
        }
        
    }

 

Share this post