iOS Programming Basics
Creating mobile apps for both iOS and web deployment is fun and rewarding. With Xcode in place, you are ready to write code, build, and run iOS apps now. Objective-C had been the primary programming language for iOS apps until Swift was officially announced at the 2014 Apple Worldwide Developers Conference. If you’re just starting to learn iOS programming, you should go with Swift because there is no reason to choose the old way and miss the latest and greatest features. Your next steps should be learning the fundamentals of the following:
The purpose of this chapter is to get you comfortable with reading the Swift code in this book. To achieve this goal, you will be creating a HelloSwift project while learning about Swift programming language highlights.
You will create another Xcode iOS project in the second part of the chapter. All iOS apps have a user interface (UI). You normally start by creating the UI using the most important Xcode tool, the storyboard editor, which draws the UI widgets and components and connects them to your code. You also will see the typical iOS project structures and components while creating this iOS app. You may not need to understand everything about the iOS framework in the beginning, but the first storyboard lesson should be “just enough” for you to get a feel for the different programming paradigm. Later, the materials in Chapters 3 and 4 continue with step-by-step instructions for common programming tasks and framework topics. Follow these mapping instructions, and the ideas will more easily stick with you as you get a broader picture of the whole app.
The Swift Language in a Nutshell
Swift is the newest programming language for creating iOS apps. I am confident that learning the Swift language won’t be the highest hurdle for you; JavaScript and C# developers will pick up Swift code naturally because they are syntactically similar and follow the conventions of typical object-oriented (OO) programming languages. Just to give you a quick preview, Table 2-1 briefly compares JavaScript to Swift.
Table 2-1. Java-to-Swift Language Syntax Comparison in a Nutshell
JavaScript |
Swift |
---|---|
<script type="text/javascript" src="scripts/packagename/Xyz.js"></script> |
import framework |
Xyz.prototype = new SomeClass(); |
class Xyz : SomeClass |
var mProperty; |
var mProperty : Int |
Xyz.prototype.constructor=Xyz // constructor |
init() |
var obj = new Xyz(); |
var obj : Xyz = Xyz() |
Xyz.prototype.doWork(arg) |
func doWork (arg: String) -> Void |
obj.doWork(arg); |
obj.doWork(arg) |
The Table 2-1 cross-reference refers to how native JavaScript prototype-based inheritance might be used to implement classical inheritance used by Swift, Java, and C#. For those familiar with Prototype and Sencha, the extension libraries and methods for inheritance should make the transition even more straightforward. If you come from a basic JQuery programming background, the syntax of Swift will seem familiar, but the structure of your code will move from a flat list of functions to encapsulated objects and object instances with a hierarchal source structure. In this section, I will not discuss the in-depth OO theory or techniques. However, I do want to point out certain important ideas for pure-JavaScript developers.
HelloSwift with Xcode
Instead of my describing the uses and syntax rules in a formal way, you are going to create a HelloSwift Xcode project and write the code listing from Table 2-1 yourself. You will also perform the following common Xcode programming tasks: creating a class, building and running a project, and using the debugger.
Creating a Swift Command-Line Project
Let’s create a command-line Swift program because it is really simple and you can focus on the Swift language without being sidetracked by other questions.
Follow these instructions to proceed:
Figure 2-1. Choosing an Xcode template
Figure 2-2. Creating the HelloSwift project
The command-line template creates the main.swift file for you. This is the entry point of the OS X command line tool program. You will be writing code in main.swift to demonstrate common object-oriented code.
Figure 2-2 shows that the typical Xcode workspace contains three areas from left to right and a top toolbar. Inside each area, there are subviews that you may switch to using the selector bars.
Click any of the icons on the selector bars, or hover your mouse over the pointer in Figure 2-2, to see the hover text tips in the workspace to get yourself familiar with Xcode workspace. The subviews appear more condensed than those in most of the IDE I ever experienced, but essentially it is a tool for the same purpose: editing project files and compiling, building, debugging, and running the executables. You will use it repeatedly throughout the book.
A class is the fundamental building block of any classic OO programming language. A class is a software template that defines what the objects know (state) and how the objects behave (methods). JavaScript uses functions and their prototypes to accomplish the same goal.
While JavaScript web applications often make use of objects by creating and manipulating DOM elements, it is entirely possible to create a JavaScript web application without creating a single new reusable object structure. Using anonymous objects and scripts running in the global scope, referencing function libraries like JQuery, is quite common. Swift, however, requires developers to structure their code into named class types before the objects can be created.
To create a new Swift class, you can create it in the existing main.swift file, or you can follow the Java convention to create it in its own file as shown in the following steps:
Figure 2-3. Create a Swift class from the folder context menu
Note Unlike Java, a Swift class doesn’t implicitly inherit from any class. It can be the base class on its own.
Listing 2-1. Declare MobileDeveloper Class
class MobileDeveloper {
}
Listing 2-2. Stored Property in Swift
class MobileDeveloper {
var name = "" // var type, String, is inferred by the value
}
Note The semicolon (;) is optional for terminating a statement in the same line.
Creating a Swift Protocol
WEB ANALOGY
Though JavaScript has no native comparable for a Swift protocol, web developers using C# or PHP for their server-side code will find comparable examples in the use of interfaces.
In object-oriented programming (OOP), an interface or protocol is essentially a predefined set of behaviors, methods, or properties. The protocol provides no implementation of the methods themselves but rather defines the method names, parameters, and return types. Consumers of the protocol can count on objects they are consuming to properly implement the items defined in the protocol. Protocols allow objects of different types and class inheritance to provide a common, strongly typed interface, thus implementing the concept of polymorphism, one of the fundamental concepts of OOP. You may also provide multiple implementation classes for the same contract and programmatically supply the appropriate instances in the runtime.
In simpler terms, this is a great way to explicitly break dependencies between callers and callees because callers and callees can be implemented independently with clearly defined programming contracts, called protocols in Swift.
Create a Swift protocol called Programmer by doing the following:
Listing 2-3. Declare the Programmer Protocol
protocol Programmer {
func writeCode(arg: String) -> Void
}
To conform to the expected behavior defined in a Swift protocol, the tagged class must implement the methods defined in the protocol. To make the MobileDeveloper class implement the Programmer protocol, do the following:
Listing 2-4. Conform to MobileDeveloper Protocol
class MobileDeveloper : Programmer {
...
}
Note If the Swift class already has a superclass, list the superclass name before any protocols it adopts, followed by a comma (,)—for example:
class MobileDeveloper : Person, Programmer
Listing 2-5. Method Body
class MobileDeveloper: Programmer {
...
func writeCode(arg: String) -> Void {
println("(self.name) wrote: Hello, (arg)")
}
}
Note (self.name) is evaluated first inside the quoted String literal.
Using the Swift Instance
WEB ANALOGY
you.setName("You");
you.writeCode("Javascript");
You have created a Swift MobileDeveloper class and implemented the Programmer obligations in pretty much the same way you would in Java with some minor syntax differences. To use the class, it is the same as Java in principle, calling a method defined in the receiver from the sender. Modify HelloSwift/main.swift as shown in Listing 2-6.
Listing 2-6. Swift Entry main.swift
var you = MobileDeveloper()
you.name = "You"
you.writeCode("Java")
WEB ANALOGY
While JavaScript doesn’t have access control keywords, many JavaScript developers use closures and constructor variables to create methods and variables with private access from the object.
Here’s an example:
function MyObject() {
var private;
this.getPrivate = function (arg) {
return private;
}
this.setPrivate = function (val) {
private=val;
}
}
var test =new MyObject();
test.setVal("My private value");
console.log("Private value is "+test.getVal());
Encapsulation is one of the fundamental principles of OOP; in a nutshell, certain internal states or methods are meant only for internal implementations but not to be used directly by the callers. Swift provides access controllers to prevent access to the members or methods that developers decide to hide. This is achieved with access modifiers for files and with module access controls using the following keywords as the access modifiers: private, public, and internal. The internal access modifier is the default access control that is public to the whole module but not visible when the modules are imported. If you are building a reusable module that can be imported by other program, use the public access modifier to expose the API to another module. The private access modifier makes your custom classes or type or members visible only within the file scope.
To demonstrate the private access control, modify MobileDeveloper.swift as shown in Listing 2-7.
Listing 2-7. The private Access Modifier in MobileDeveloper
private class MobileDeveloper {
var name = "" // var type is infered by the value
func writeCode(arg: String) -> Void {
// some dummy implementation
println("(self.name) wrote: Hello, (arg)")
}
private func doPrivateWork() {
println(">> doPrivateWork")
}
}
// another class in the same source file
class TestDriver {
func testDoPrivateWork() -> Void {
var developer = MobileDeveloper()
developer.doPrivateWork()
}
}
Since TestDriver is implemented in the same source file, the code in TestDriver still can access the private class and its private method. However, the MobileDeveloper class in Listing 2-6 becomes not visible anymore from the main.swift file.
Knowing how to use the debugger when creating software can make a big difference in your productivity. Do the following to see the common debugging tasks in the Xcode debugger:
Figure 2-4. Breakpoint
Note To turn on line numbers in Xcode editors, go to the Xcode top menu bar and select Xcode Preferences Text Editing Show Line Numbers. There are other handy settings there that you may want to look at (for example, shortcut keys are defined under Key Binding).
Figure 2-5. Xcode debugging
Stack Trace (in Debug navigator), Variables Inspector, Output Console, and the Debug toolbar (in Debug area) have a similar look and feel in most IDEs, including Xcode.
This completes your HelloSwift application exercise. As you follow along with the iOS projects in this book, you will discover more productivity tips in the Xcode IDE.
More About the Swift Language
The new Xcode environment and the Swift language have some pretty neat features, so it’s worth taking a quick look at them now.
To go through this section, it is best to use the new Xcode feature called playgrounds. Launch Xcode and select “Get started with a playground.” You can write any code snippets you want and see the result or syntax errors immediately. Figure 2-6 shows the playground; you write code in the left panel, and the right panel renders the result immediately.
Figure 2-6. Xcode playground
JAVASCRIPT ANALOGY
Browser developer tools, JavaScript console, or JSFiddle give you immediate feedback for the Javascript code you write.
You declare a variable using the var keyword, and you use let to declare constants. Similar to JavaScript, Swift variables are global if defined not within any enclosing brackets. Listing 2-8 depicts the usage of Swift variables.
Listing 2-8. Common Variables Usages
var GlobalVar : String = "Global Variable"; // global scope not enclosed in any brackets
class MyClass {
var mProperty : String = ""; // class scope
let mConstant : Int = 0; // constant
func myMethod(arg : String) {
var aVar : String = ""; // local variable in method scope
let aConstant = 1;
}
}
Type Safety and Type Inference
Unlike Swift, JavaScript is a weakly typed language. A JavaScript variable can be assigned values of any type or passed as a parameter to a function that expects a value of a completely different type or no parameters at all. JavaScript’s lack of strong typing can result in code that is vulnerable to runtime errors, especially as web applications grow in size and complexity.
As a strongly typed language, Swift requires that all variables be declared with a type that they will keep through their lifetime, with the compiler flagging any mismatched types. If the type of a variable can be inferred by its value, you don’t need to explicitly declare the type. Listing 2-9 is essentially the same as Listing 2-8. The Swift type inference feature encourages developers to assign initial values that reduce common errors because of variables not initialized yet.
Listing 2-9. Common Type Inference Usages
var GlobalVar = "Global Variable"
class MyClass {
var mProperty = ""
let mConstant = 0
func myMethod(arg : String) {
var aVar = "";
let aConstant = 1
}
}
The optional variables are declared with the type and a postfixed question mark (?), called an optional type. This indicates the value it contains may be absent (nil, equivalent to undefined in JavaScript) for the intended type. For example, Listing 2-10 depicts the difference in Swift and JavaScript for converting a string to an integer.
Listing 2-10. Optional Type in Swift vs. Handle Exception in JavaScript
////// Javascript TypeError
function StringToInt(str) {
}
var intStr;
var int
function useObject(objParm) {
try {
objParm.badFunction()
} catch(err) {
console.log(err);
}
}
var undefinedObject;
useObject(undefinedObject);
////// Swift Optional Int
var intStr = "123"
var myInt : Int? = intStr.toInt() // myInt can be nil
Optionals make the Swift language more type-safe and more robust by encouraging developers to understand whether the variable can be absent. Listing 2-11 demonstrates two practical Swift optional usages.
Listing 2-11. Swift Optional Int
var intStr = "123"
var myOptionalInt : Int? = intStr.toInt() // Optional Int
if myOptionalInt != nil {
var myInt = myOptionalInt! // Unwrap Int? to Int
println("unwrapped Int: (myInt)")
}
// optional binding used in if and while local scope.
if var myInt = intStr.toInt() {
// myInt is auto unwrapped
println("unwrapped and local scope: (myInt)")
}
Implicitly Unwrapped Optionals
For the situations where a variable will always have a value after the value is set, you declare the variable as an implicitly unwrapped optional postfixed with ! instead of ?, as in var delegate: MyDelegate!.
Any of the optionals’ usages described earlier are applicable here. You treat them as optionals, but you don’t need to force unwrapping the variable (Implicitly Unwrapped Optionals). You commonly see this usage in the iOS framework for properties that are initialized somewhere else (in other words, by the caller). Particularly, iOS frameworks embed delegate properties everywhere. These delegates are declared as implicitly unwrapped optionals, but their values are typically assigned by the caller. As another example, UI widgets are normally drawn in the storyboard editor and connect to your code as IBOutlet properties. These IBOutlet properties are declared as implicitly unwrapped optionals. I just wanted to give you a quick heads up for now because you will see these usages frequently later in this book.
WEB ANALOGY
Tuples are equivalent to JavaScript objects created by literal notation, sometimes called anonymous objects.
Here’s an example:
var xyz = {x: 2, y: 3, z: 0};
var total=xyz.x+xyz.y;
console.log("Total is now:"+total);
// Displays: total is now 5
Tuples group multiple values into a single compound value. For example, you can pass or return multiple values without creating a class or a struct (structs are also supported in Swift). Listing 2-12 shows the most common tuple usages.
Listing 2-12. Common Tuple Usages
var xyz = (x: 0, y: 0, z: 0)
println("xyz (xyz) x is: (xyz.x) y is: (xyz.y) z is: (xyz.z)")
// or decompose tuples
var xy : (Int, Int) = (1, 1) // or simply var xy = (1, 1)
var (a, b) = xy
println("xy (xy) x is: (a) y is: (b)")
func httpResponse() -> (rc: Int, status: String) {
return (200, "OK")
}
var resp = httpResponse()
println("resp is: (resp.rc) (resp.status)")
JAVASCRIPT ANALOGY
JavaScript arrays are used as collections, having case-sensitive string names as the unique index.
Here’s a JavaScript example:
var colors = ['red','green','blue'];
var colorDictionary = {};
colorDictionary.red = colors[0];
Array and Dictionary are the two Swift collections. Listing 2-13 shows the common usages, which include the following:
Listing 2-13. Common Array and Dictionary Usages
// collections
var emptyArray = Array<String>() // or [String]()
var emptyDict = Dictionary<Int, String>() // [Int: String]()
var colors = ["red", "green", "blue"]
var colorDictionary = ["r" : "red", "g" : "green", "b" : "blue"]
colors.append("alpha") // or: colors += "alpha"
colorDictionary["a"] = colors[3]
colors.insert("pink", atIndex: 2)
colors.removeAtIndex(2)
println(colors.isEmpty ? "empty" : "(colors.count)")
The constant Dictionary or Array is immutable, meaning it is not allowed to add or remove elements or modify existing items. On the other hand, the variable Dictionary or Array is mutable. JavaScript has no concept of constants or access modifiers.
Similar to JavaScript, in Swift you use if and switch to make conditionals and use for-in, for, while, and do-while to make loops. Parentheses around the condition or loop variable are optional. Braces around the body are required. Listing 2-14 demonstrates the following common control flow usages:
Listing 2-14. Control Flows
for (var idx = 0; idx < 10; idx++) { // optional parenthesis
println("for-loop: (idx)")
}
for item in [1,2,3,4,5] { // or for item in 1...5
println("for-in: (item)")
}
for c in "HelloSwift" { // loop thru characters
print(c)
}
for (key, value) in colorDictionary {
println("for-in dictionary:(key) - (value)")
}
// while-loop, or do-while that run at least once
var idx = 0
while idx < colors.count {
println("while-loop: (colors[idx])")
idx++
}
In Swift, the switch cases can be any types in addition to int primitive data. Listing 2-15 shows the following improved control flow switch usages in Swift:
Listing 2-15. Improved Switch
var condition = "red"
switch condition {
case "red", "green", "blue": // combined cases
println("(condition) is a prime color")
// always break implicitly (no follow thru)
case "RED", "GREEN", "BLUE":
println("(condition) is a prime color in uppercase")
default: // not optional anymore
println("(condition) is not prime color")
}
var range = 9 // by range
switch range {
case 0:
println("zero")
case 0...9:
println("one-digit number")
case 10...99:
println("two-digit number")
case 10...999: // first hit first
println("three-digit number")
default:
println("four or more digits")
}
var coord = (0, 1)
switch coord { // by tuples
case (0...Int.max, 0...Int.max):
println("1st quad")
case (Int.min...0, 0...Int.max):
println("2nd quad")
case (Int.min...0, Int.min...0):
println("3rd quad")
case (0...Int.max, Int.min...0):
println("4th quad")
default:
println("on axis")
}
A switch can bind the matched value within its local scope. You can specify a where clause to test the condition, too. Listing 2-16 demonstrates both value bindings.
Listing 2-16. Temporary Value Binding and Using the where Clause
var rect = (10, 10)
switch rect {
case let (w, h) where w == h:
println("((w, h)) is a square")
default:
println("rectangle but not square")
}
You use an enum to define a common type for a group of named and related constant values. JavaScript has no analogous concept, often leaving developers passing numeric values to functions with code comments to explain the meaning of each numeric value. After the enumeration is defined, you use it just as a Swift type that is type-safe. Listing 2-17 shows the following common enum usages:
Listing 2-17. Common Enum Usages
enum DayOfWeek { // raw value is optional
case SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
var aDay = DayOfWeek.SUNDAY
switch aDay {
case DayOfWeek.SATURDAY, DayOfWeek.SUNDAY:
println("(aDay) is weekend")
default:
println("(aDay) is weekday")
}
enum DayOfWeek2 : String { // assign raw value
case SUNDAY = "Sun", MONDAY = "Mon", TUESDAY = "Tue",
WEDNESDAY = "Wed", THURSDAY = "Thu", FRIDAY = "Fri", SATURDAY = "Sat"
}
var aDay2 = DayOfWeek2.SUNDAY
switch aDay2 {
case DayOfWeek2.SATURDAY, DayOfWeek2.SUNDAY:
println("(aDay2.rawValue) is weekend")
default:
println("(aDay2.rawValue) is weekday")
}
// associated values
enum Color {
case RGB(Int, Int, Int)
case HSB(Float, Float, Float)
}
var aColor = Color.RGB(255, 0, 0)
switch aColor {
case var Color.RGB(r, g, b):
println("R: (r) G: (g) B: (b) ")
default:
println("")
}
Swift functions are declared with the func keyword. Unlike JavaScript functions, which do not declare a return type, the parameter and return types must be declared after the parameter names and function signature. Here are the typical Swift function usages you most likely will encounter (see Listing 2-18):
Note The second type of closure is the global function mentioned right here, which is actually a special case of closure. The third type of closure is called a nested function declared inside a function, which is not used in this book.
Listing 2-18. Function Usages
func doWork(parm : String) -> String { // simple form
return "TODO: " + parm
}
println(doWork("Swift"))
// External parameter names is part of the func signature
func doWork2(name parm : String) -> String {
// arg = arg.uppercaseString; // error: constant parm
return "TODO: " + parm
}
println(doWork2(name: "Swift"))
// use # to indicate same name for internal and external
func doWork3(#name: String) -> String {
return "TODO: " + name
}
println(doWork3(name: "Swift"))
// With default parm value, it also implies #, same external name
func doWork4(name: String = "Swift") -> String {
return "TODO: " + name
}
println(doWork4()) // default parm value
// parm is constant by default unless declaring it with var
func doWork5(var name: String = "Swift") -> String {
name = name.uppercaseString;
return "TODO: " + name;
}
// variadic parms
func sumNumbers(parms : Int...) -> Int {
var sum = 0
for number in parms {
sum += number
}
return sum
}
println(sumNumbers(2,5,8))
// func is a type, can be used for parm or return type.
func separateByAnd(p1: String, p2: String) -> String {
return p1 + " and " + p2
}
func printTwoString(p1: String, p2: String, format: (String, String)->String) {
println(format(p1, p2))
}
printTwoString("Horse", "Carrot", separateByAnd)
// closure expression is unnamed func
printTwoString("Horse", "Carrot",
{(p1: String, p2: String) -> String in
return p1 + " and " + p2
})
printTwoString("Horse", "Carrot",
{p1, p2 in // type inferences
return p1 + " and " + p2
})
printTwoString("Horse", "Carrot",
{ // Inference and shorthanded parm names, $0, $1 ...
return $0 + " and " + $1
})
You may get by with not using most of the shorthand options at first, but for iOS programming, you definitely will need to get used to the external parameter names because they are used heavily in iOS frameworks.
Class
Like other classic OO languages, Swift uses classes to define the shared functionality and properties of a given type. Though many web developers may be unfamiliar with the creation of classes using prototype inheritance in JavaScript, almost every web developer has made use of the JavaScript classes that define the support for DOM manipulation. The simplest Swift class form can be depicted as shown in Listing 2-19.
Listing 2-19. Simple Swift Class
class SimpleClass {
var mProperty : Int = 0
var mConstant : String = "MyKey"
func myMethod(name: String) -> Void { println(name)}
}
Listing 2-20 demonstrates the following Swift property usages:
Listing 2-20. Swift Class Property
class MyClass {
var width = 10, height = 10 // stored properties
// computed properties, can have set as well
var size : Int {
get {
return width * height
}
}
var size2 : Int { // readonly, shorthanded
return width * height
}
// property observer
var depth : Int = 10 {
willSet {
println("depth ((depth)) will be set to (newValue)")
}
didSet {
println("depth ((depth)) was set from (oldValue)")
}
}
// Swift class Type property,
class var MyComputedTypeProperty : String {
return "Only computed Type property is supported in class type for now"
}
// use struct stored Type property as a workaround
struct MyStatic {
static let MyConst = "final static in Java"
static var MyVar: String?
}
}
println(MyClass.MyStatic.MyConst)
MyClass.MyStatic.MyVar = "class var in Java"
println(MyClass.MyStatic.MyVar)
Methods are functions defined inside a type context (in other words, a class). They are still functions as described previously (see Listing 2-17). You can define instance methods, which are called on an instance of a class, or type methods, which are called on the class itself. Listing 2-21 shows the following typical method usages:
Listing 2-21. Common Method Usages
class MyClass {
///////// methods copied from Listing 2-17 //////////
func doWork(parm : String) -> String {
return "Do something with: " + parm
}
// default parm value, always imply externl parm name
func doWork2(name: String = "Swift") -> String {
return "Do something with: " + name
}
// func is a type, can be used for parm or return type.
func separateByAnd(p1: String, p2: String) -> String {
return p1 + " and " + p2
}
func printTwoString(p1:String, p2:String, format:(String, String)->String) {
println(format(p1, p2))
}
// Type methods, methods which can be called on the Class
class func DoWork(parm : String) -> String {
return "Do something with: " + parm
}
}
var c = MyClass()
println(c.doWork("Swift"))
println(c.doWork2()) // default parm value
println(c.doWork2(name: "Swift")) // external name enforced
// closure is unnamed func
c.printTwoString("Horse", p2: "Carrot", format: c.separateByAnd)
// Inference and shorthanded parm names apply to method, too.
c.printTwoString("Apple", p2: "Orange", format: {
return $0 + " and " + $1
})
MyClass.DoWork("Swift Type method")
Reference Type vs. Value Types
Just as in JavaScript, reference types are passed by reference (the reference to the instance is copied to another variable), and values types are passed by copy (the whole value type instance is copied to another memory space). However, you do need to pay attention to certain differences.
iOS Project Anatomy
Most GUI apps are composed of more than programming source code; for example, a typical iOS project contains Swift or Objective-C source code, libraries, storyboard files, images or multimedia noncode application resources, an application-information property Info.plist file, and so forth. Xcode compiles and builds the whole project and bundles all the artifacts required for an app into an archive file with an .app file extension and signs the .app file with the appropriate signing certificate.
Let’s create a simple HelloMobile Xcode project so that you can visualize these software artifacts in a typical iOS project.
To create the HelloMobile iOS app, start Xcode and proceed with the following steps:
Figure 2-7. Single View Application template
The bare-bones HelloMobile iOS project is created, and it now appears in the Xcode Project Navigator area (see Figure 2-8).
Figure 2-8. HelloMobile project
It is immediately runnable. Let’s examine the typical iOS software artifacts in an Xcode project, which comprise the iOS app.
The iOS app is not completed yet, but it has everything a typical iOS app should have.
Xcode Storyboard
WEB ANALOGY
There is no storyboard-like feature in most web dev environments. Views are normally either built one at a time in a quasi-WYSIWIG markup editor (Visual Studio, Eclipse, and so on) or, more often than not, built in a text editor for use with libraries such as Handlebars or Knockout. Even web developers familiar with Sencha Architect will find the storyboard designer’s presentation of application flow to be tremendously powerful and intuitive by comparison.
Use the Xcode storyboarding feature to visually compose the UI for your app. As its name implies, not only does it create individual screens and UI widgets, but it also lets you compose the whole app as one storyboard. Since iOS apps are all GUI apps, this tool will greatly determine your productivity in creating iOS apps through the following actions:
There are other subviews in the Utility area that you can select from the top selector toolbar. All of them are important; you should take a moment to get familiar with them.
Now is the time for you to get familiar with the Xcode storyboarding feature. The iOS HelloMobile project doesn’t look like the complete app yet; it has only one screen in the Main.storyboard file, which is empty. You will need to add three UI widgets: EditText, TextView, and a hello Button.
First you will implement the user interface of the HelloMobile iOS app. Xcode storyboards provide everything you need for this mission.
Object Library and Attributes Inspector
WEB ANALOGY
Many web developers find themselves building their markup and code in a tool of their choosing, running the application in a browser with the developer tools open, and inspecting and manipulating the attributes of their layout directly from the browser.
You need to add three UI widgets to the content view using the following steps:
Figure 2-9. Select UI components from the Object Library
Figure 2-10. Disable Use Size Classes in File Inspector
Tip The iOS widgets you need are called UITextField, UILabel, and UIButton.
Figure 2-11. Guide lines
Figure 2-12. Three simple UI widgets
Figure 2-13. Three simple widgets added to the storyboard
The look and feel in portrait mode is close enough for our purposes, in other words, using a storyboard to visually compose the content view without writing a single line of code. The iOS HelloMobile is not completed yet. The Hello button doesn’t read “Hello...,” and the landscape mode is not acceptable yet. Both are important topics and have their own sections in Chapter 3.
In this exercise, I just wanted to give you a quick look at the Xcode storyboard editor. The Xcode workspace could be a little overwhelming if you are not used to using any IDE. Spend a moment to get familiar with the Xcode workspace, including the storyboard editor, the Utility area, the selector toolbar, and so forth. Xcode storyboarding is an important tool that will greatly influence your productivity when creating iOS apps.
Summary
On the surface, you learned about a lot of things in this chapter. I started with a discussion of Swift–JavaScript language comparisons to show their similarities, and then I went over Swift language topics to highlight the new language features. However, the rest of the book will focus on iOS programming instead of the Swift language. The code will address readability as opposed to being concise using shorthanded notations or Swift tricks. You surely won’t have a problem reading all the Swift code in the rest of the book. Sooner or later, though, you will need the reference document to the Swift programming language, which is available free in iTunes (https://itunes.apple.com/us/book/swift-programming-language/id881256329).
You created a HelloMobile iOS project using Xcode to visualize a typical iOS application structure. You also got your first taste of the Xcode storyboard, which is important and which you will use for every iOS app, including all the sample projects in this book, so plan on revisiting the storyboard repeatedly.