One of the great things about being an iOS developer is you get to tell your devices exactly what you want them to do and they do it—your devices will do tasks over and over again without getting tired. That’s because iOS devices don’t care how hard they worked yesterday, and they don’t let feelings get in the way. These devices don’t need hugs.
There is a downside to being a developer: you have to think of all the possible outcomes when it comes to your apps. Many developers love having this kind of control. They enjoy focusing on the many details of their apps; however, it can be frustrating having to handle so many details. As mentioned in the introduction to this book, there is a price to pay for developing apps, and that price is time. The more time you spend developing and debugging, the better you will get with all the details, and the better your apps will perform. You have to pay this price to become a successful developer.
Computers are black and white; there are no shades of gray. Your devices produce results, many of which are based on true and false conditions.
In this chapter, you learn about computer logic and controlling the flow of your apps. Processing information and arriving at results are at the heart of all apps. Your apps need to process data based on values and conditions. To do this, you need to understand how computers perform logical operations and execute code based on the information your apps have acquired.
Boolean Logic
Boolean logic is a system for logical operations. Boolean logic uses binary operators such as AND and OR and the unary operator NOT to determine whether your conditions have been met. Binary operators take two operands. Unary operators take one operand.
We just introduced a couple of new terms that can sound confusing; however, you probably use Boolean logic every day. Let’s look at a couple of examples of Boolean logic with the binary operators AND and OR in a conversation parents sometimes have with their teenage children:
“You can go to the movies tonight if your room is clean AND the dishes are put away.”
“You can go to the movies tonight if your room is clean OR the dishes are put away.”
In the preceding example, the AND operator takes two operands: one to the left and one to the right of the AND. Each operand can be evaluated independently with a TRUE or FALSE.
For an AND operation to yield a TRUE result, both sides of the AND have to be TRUE. In the first example, the teenager has to clean his or her room AND have the dishes done. If either one of the conditions is FALSE, the result is FALSE—no movies for the teenager.
For an OR operation to yield a TRUE result, only one operand has to be TRUE, or both conditions can be TRUE to yield a TRUE result. In the second example, just a clean bedroom would result in the ability to go to the movies.
Note
In Objective-C and other programming languages, Boolean variables can hold integer variables; 0 represents FALSE, and any nonzero value represents TRUE. Swift’s strong type checking doesn’t allow this. Boolean variables in Swift can be assigned only true or false.
A NOT statement is a unary operator. It takes just one operand to yield a Boolean result. Here’s an example:
“You can NOT go to the movies.”
This example takes one operand. The NOT operator turns a TRUE operand to a FALSE and a FALSE operand to a TRUE. Here, the result is a FALSE.
AND, OR, and NOT are three common Boolean operators. Occasionally, you need to use more complex operators. XOR, NAND, and NOR are other common operations for iOS developers.
The Boolean operator XOR means exclusive-or. An easy way to remember how the XOR operator works is the XOR operator will return a TRUE result if only one argument is TRUE, not both.
Swift does not have the NAND and NOR operators built in, but just know that they simply mean NOT AND and NOT OR, respectively. After evaluating the AND or OR arguments, simply negate the result.
Truth Tables
You can use a tool to help you evaluate all the Boolean operators called a truth table, and it is a mathematical table used in logic to evaluate Boolean operators. They are helpful when trying to determine all the possibilities of a Boolean operator. Let’s look at some common truth tables for AND, OR, NOT, XOR, NAND, and NOR.
TRUE AND TRUE = TRUE
TRUE AND FALSE = FALSE
FALSE AND TRUE = FALSE
FALSE AND FALSE = FALSE
An AND Truth Table
A | B | A AND B |
---|---|---|
TRUE | TRUE | TRUE |
TRUE | FALSE | FALSE |
FALSE | TRUE | FALSE |
FALSE | FALSE | FALSE |
An AND truth table produces a TRUE result only if both of its operands are TRUE.
An OR Truth Table
A | B | A OR B |
---|---|---|
TRUE | TRUE | TRUE |
TRUE | FALSE | TRUE |
FALSE | TRUE | TRUE |
FALSE | FALSE | FALSE |
An OR truth table produces a TRUE result if one or both of its operands are TRUE.
A NOT Truth Table
A | NOT A |
---|---|
TRUE | FALSE |
FALSE | TRUE |
A NOT flips the bit or negates the original operand’s Boolean value.
An XOR Truth Table
A | B | A XOR B |
---|---|---|
TRUE | TRUE | FALSE |
TRUE | FALSE | TRUE |
FALSE | TRUE | TRUE |
FALSE | FALSE | FALSE |
The operator XOR yields a TRUE result if only one of the operands is TRUE.
A NAND Truth Table
A | B | A NAND B |
---|---|---|
TRUE | TRUE | FALSE |
TRUE | FALSE | TRUE |
FALSE | TRUE | TRUE |
FALSE | FALSE | TRUE |
A NOR Truth Table
A | B | A NOR B |
---|---|---|
TRUE | TRUE | FALSE |
TRUE | FALSE | FALSE |
FALSE | TRUE | FALSE |
FALSE | FALSE | TRUE |
The easiest way to look at the NAND and NOR operators is to simply negate the results from the AND and OR truth tables, respectively.
Comparison Operators
Comparison Operators
Operator | Definition |
---|---|
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
== | Exactly equal to |
!= | Not equal to |
Note
If you’re constantly forgetting which way the greater than and less than signs go, use a crutch we learned in grade school: if the greater than and less than signs represent the mouth of an alligator, the alligator always eats the bigger value. It may sound silly, but it works.
Designing Apps
Now that we’ve introduced Boolean logic and comparison operators, you can start designing your apps. Sometimes it’s important to express all or parts of your apps to others without having to write the actual code.
Writing pseudocode helps a developer think out loud and brainstorm with other developers regarding sections of code that are of concern. This helps to analyze problems and possible solutions before coding begins.
Pseudocode
Pseudocode refers to writing code that is a high-level description of an algorithm you are trying to solve. Pseudocode does not contain the necessary programming syntax for coding; however, it does express the algorithm that is necessary to solve the problem at hand.
Pseudocode can be written by hand on paper (or a whiteboard) or typed on a computer.
Using pseudocode, you can apply what you know about Boolean data types, truth tables, and comparison operators. Refer to Listing 4-1 for some pseudocode examples.
Note
Pseudocode is for expressing and teaching coding ideas. Pseudocode will not execute!
Pseudocode Examples Using Conditional Operators in if-then-else Code
Note that ! switches the value of the Boolean it’s applied to, so using ! makes a TRUE value into a FALSE and makes a FALSE value into a TRUE. This is the logical NOT operator in Swift.
Often, it is necessary to combine your comparison tests. A compound relationship test is one or more simple relationship tests joined by either && or || (two pipe characters).
Using && and || Logical Operators Pseudocode
Optionals and Forced Unwrapping
Chapter 3 introduced optionals. Optionals are variables that might not contain a value. Since optionals may not contain a value, you need to check for that before you access them.
You start by using an if statement to determine whether the optional contains a value by comparing the optional against nil. If the optional has a value, it is considered to be “not equal to” nil, as shown in Listing 4-3.
Checking Whether an Optional Has a Value
Forced Unwrapping
Note
Displaying the contents of a variable in a print function is done with \().
Optional Binding
Optional Binding Syntax to a Constant
Optional Binding Syntax to a Variable
Notice in Listings 4-5 and 4-6 that you didn’t need to force unwrap anything using the !. If the conversion was successful, the variable or constant was initialized with the value contained within the optional, so the ! was not necessary.
It may be confusing that the logical NOT and forced unwrapping operators both use the ! character. Just remember that the logical NOT operator is located before a variable or constant, and the forced unwrapping operator is located after an optional constant or variable.
Implicitly Unwrapped Optionals
There are instances in your code when you know that an optional will always have a value. In these instances, it can be useful to remove the need to check and unwrap an optional every time it needs to be accessed. These kinds of optionals are called implicitly unwrapped optionals .
Comparison of an Optional String and an Implicitly Unwrapped Optional String
Flowcharting
Flowcharts should always have a start and a stop. Branches should never come to an end without a stop. This helps developers make sure all of the branches in their code are accounted for and that they cleanly stop execution.
Designing and Flowcharting an Example App
We have covered a lot of information about decision making and program flow. It’s time to do what programmers do best: write apps!
The app you have been assigned to write generates a random number between 0 and 100 and asks the user to guess the number. Users have to do this until the number is guessed. When users guess the correct answer, they will be asked if they want to play again.
The App’s Design
Reviewing Figure 4-2, you’ll notice that as you approach the end of a block of logic in your flowchart, there are arrows that go back to a previous section and repeat that section until some condition is met. This is called looping . It enables you to repeat sections of programming logic—without having to rewrite those sections of code over—until a condition is met.
Using Loops to Repeat Program Statements
A loop is a sequence of program statements that is specified once but can be repeated several times in succession. A loop can repeat a specified number of times (count-controlled) or until some condition (condition-controlled) occurs.
In this section, you’ll learn about count-controlled loops and condition-controlled loops. You will also learn how to control your loops with Boolean logic.
Count-Controlled Loops
A Count-Controlled Loop
The loop in Listing 4-8 will loop 10 times. The “half-open range operator” ..< returns a sequence of values from the “lower bound” value 0 up to, but not including, the “upper bound” value 10, resulting in values of i between 0 and 9.
A Count-Controlled Loop Using the Closed-Range Operator
Condition-Controlled Loops
A Swift while Loop Repeating
The while loop in Listing 4-10 first checks whether the variable isTrue is true—which it is—so the {loop body} is entered where the code is executed. Eventually, some condition is reached that causes isTrue to become false. After completing all the code in the loop body, the condition (isTrue) is checked once more, and the loop is repeated. This process is repeated until the variable isTrue is set to false.
Infinite Loops
An infinite loop repeats endlessly, either because of the loop not having a condition that causes termination or because of the loop having a terminating condition that can never be met.
Generally, infinite loops can cause apps to become unresponsive. They are the result of a side effect of a bug in either the code or the logic.
An Example of an Infinite Loop
An Example of an Infinite Loop Caused by a Terminating Condition That Can Never Be Met
Coding the Example App in Swift
Using your requirements and what you learned, try writing your random number generator in Swift.
To program this app, you have to leave the playground and do this as a Mac Console app. Unfortunately, at this time, a playground doesn’t enable you to interact with a running app, so you can’t capture keyboard input.
- 1.Open Xcode and select Create a new Xcode project. Choose the Command Line Tool macOS project as seen in Figure 4-3 and click Next.
- 2.Call your project RandomNumber (see Figure 4-4). Ensure that the Language drop-down is Swift and click Next. Save the project anywhere you prefer on your hard drive and click Create.
- 3.
Open the main.swift file. Write the code in Listing 4-13.
Source Code for Your Random Number Generator App
This line will produce a random number between 0 and 100. arc4random_uniform()is a function that returns a random number.
This enables you to get keyboard input for the user. We will talk about this syntax in later chapters.
Int takes a string initializer and converts it to an integer.
Nested if Statements and else if Statements
Removing Extra Characters
Reading keyboard input can be difficult. In this case, it leaves a remnant at the end of your string, \n, and you need to remove it. This is a newline character that is generated when the users press the Return key on their keyboards. The trimmingCharacters(in: .whitespacesAndNewlines) method returns a new string with any blank space or newline characters removed from the beginning or end of the original string.
Improving the Code Through Refactoring
Often, after you get your code to work, you examine the code and find more efficient ways to write it. The process of rewriting your code to make it more efficient, maintainable, and readable is called code refactoring .
As you review your code in Swift, you will often notice that you can eliminate some unnecessary code.
Note
As developers, we have found that the best line of code is the line that you don’t have to write—less code means less to debug and maintain.
Running the App
Note
If you’re not seeing the output console when you run your app, make sure you have selected the same options at the top-right and bottom-right corners of the editor (choose View ➤ Debug Area ➤ Activate Console).
Design Requirements
As discussed in Chapter 1, the most expensive process in the software development life cycle is writing code. The least expensive process in the software development life cycle is gathering the requirements for your application; yet, this latter process is the most overlooked and least used in software development.
Design requirements usually begin by asking clients, customers, and/or stakeholders how the application should work and what problems it should solve.
View: Accounts view.
Description: Displays the list of accounts the user has. The list of accounts will be in the following sections: Business Accounts, Personal Accounts and Car Loans, IRA, and Home Equity Loans.
Cells: Each cell will contain the account name, the last four digits of the account, the available balance, and the present balance.
Many developers believe that design requirements take too long and are unnecessary. This is not the case. There is a lot of information presented on the Accounts screen in Figure 4-6. Many business rules can determine how information is displayed to the users, along with all of the error handling when things go bad. When designing your app, working with all the business stakeholders at the beginning of the development process is critical to getting it right the first time.
Additionally, Apple recommends that developers spend at least 50 percent of their development time on the user interface’s design and development.
Summary
This chapter covered a lot of important information on how to control your applications; program flow and decision-making are essential to every iOS app. Make sure you have completed the Swift example in this chapter. You might review these examples and think you understand everything without having to write this app. This will be a fatal mistake that will prevent you from becoming a successful iOS developer. You must spend time coding this example. Developers learn by doing, not by reading.
AND
OR
XOR
NAND
NOR
NOT
Truth tables
Negation
All comparison operators
Application requirement
Logical AND (&&)
Logical OR (||)
Optionals and forced unwrapping
Optional binding
Implicitly unwrapped optionals
Flowchart
Loop
Count-controlled loops
For loop
Condition-controlled loops
Infinite loops
While loops
Nested if statements
Code refactoring
Exercises
Extend the random number generator app to print to the console how many times the user guessed before guessing the correct random number.
Extend the random number generator app to print to the console how many times the user played the app. Print this value to the console when the user quits the app.