Swift Basic Concepts

The Basics

Swift is a new programming language for iOS, macOS, watchOS, and tvOS app development. Nonetheless, many parts of Swift will be familiar from your experience of developing in C and Objective-C.

Swift provides its own versions of all fundamental C and Objective-C types, including Int for integers, Doubleand Float for floating-point values, Bool for Boolean values, and String for textual data. Swift also provides powerful versions of the three primary collection types, ArraySet, and Dictionary, as described in Collection Types.

Like C, Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use of variables whose values cannot be changed. These are known as constants, and are much more powerful than constants in C. Constants are used throughout Swift to make code safer and clearer in intent when you work with values that do not need to change.

In addition to familiar types, Swift introduces advanced types not found in Objective-C, such as tuples. Tuples enable you to create and pass around groupings of values. You can use a tuple to return multiple values from a function as a single compound value.

Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Using optionals is similar to using nil with pointers in Objective-C, but they work for any type, not just classes. Not only are optionals safer and more expressive than nil pointers in Objective-C, they are at the heart of many of Swift’s most powerful features.

Swift is a type-safe language, which means the language helps you to be clear about the types of values your code can work with. If part of your code expects a String, type safety prevents you from passing it an Int by mistake. Likewise, type safety prevents you from accidentally passing an optional String to a piece of code that expects a nonoptional String. Type safety helps you catch and fix errors as early as possible in the development process.


Constants and Variables : 

Declaring Constants and Variables : 

Constants and variables must be declared before they are used. You declare constants with the let keyword and variables with the var keyword. Here’s an example of how constants and variables can be used to track the number of login attempts a user has made:


  1. let maximumNumberOfLoginAttempts = 10
  2. var currentLoginAttempt = 0

This code can be read as:
“Declare a new constant called maximumNumberOfLoginAttempts, and give it a value of 10. Then, declare a new variable called currentLoginAttempt, and give it an initial value of 0.”
In this example, the maximum number of allowed login attempts is declared as a constant, because the maximum value never changes. The current login attempt counter is declared as a variable, because this value must be incremented after each failed login attempt.

Type Annotations

This example provides a type annotation for a variable called welcomeMessage, to indicate that the variable can store String values:
  1. var welcomeMessage: String

The colon in the declaration means “…of type…,” so the code above can be read as:
“Declare a variable called welcomeMessage that is of type String.”
The phrase “of type String” means “can store any String value.” Think of it as meaning “the type of thing” (or “the kind of thing”) that can be stored.

Naming Constants and Variables

Constant and variable names can contain almost any character, including Unicode characters:


  1. let π = 3.14159
  2. let 你好 = "你好世界"
  3. let 🐶🐮 = "dogcow"

Constant and variable names cannot contain whitespace characters, mathematical symbols, arrows, private-use (or invalid) Unicode code points, or line- and box-drawing characters. Nor can they begin with a number, although numbers may be included elsewhere within the name.

Tuples

Tuples group multiple values into a single compound value. The values within a tuple can be of any type and do not have to be of the same type as each other.

In this example, (404, "Not Found") is a tuple that describes an HTTP status code. An HTTP status code is a special value returned by a web server whenever you request a web page. A status code of 404 Not Foundis returned if you request a webpage that doesn’t exist.


  1. let http404Error = (404, "Not Found")
  2. // http404Error is of type (Int, String), and equals (404, "Not Found")

You can create tuples from any permutation of types, and they can contain as many different types as you like. There’s nothing stopping you from having a tuple of type (Int, Int, Int), or (String, Bool), or indeed any other permutation you require.


  1. let (statusCode, statusMessage) = http404Error
  2. print("The status code is \(statusCode)")
  3. // Prints "The status code is 404"
  4. print("The status message is \(statusMessage)")
  5. // Prints "The status message is Not Found"
  6. let http200Status = (statusCode: 200, description: "OK")
If you name the elements in a tuple, you can use the element names to access the values of those elements:
  1. print("The status code is \(http200Status.statusCode)")
  2. // Prints "The status code is 200"
  3. print("The status message is \(http200Status.description)")
  4. // Prints "The status message is OK"
Tuples are particularly useful as the return values of functions. A function that tries to retrieve a web page might return the (Int, String) tuple type to describe the success or failure of the page retrieval. By returning a tuple with two distinct values, each of a different type, the function provides more useful information about its outcome than if it could only return a single value of a single type. For more information, see Functions with Multiple Return Values.

Optionals : 

You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn’t a value at all.

If you define an optional variable without providing a default value, the variable is automatically set to nil for you:
  1. var surveyAnswer: String?
  2. // surveyAnswer is automatically set to nil

If Statements and Forced Unwrapping : 

You can use an if statement to find out whether an optional contains a value by comparing the optional against nil. You perform this comparison with the “equal to” operator (==) or the “not equal to” operator (!=).
If an optional has a value, it is considered to be “not equal to” nil:

  1. if convertedNumber != nil {
  2. print("convertedNumber contains some integer value.")
  3. }
  4. // Prints "convertedNumber contains some integer value."

Optional Binding

You use optional binding to find out whether an optional contains a value, and if so, to make that value available as a temporary constant or variable. Optional binding can be used with if and while statements to check for a value inside an optional, and to extract that value into a constant or variable, as part of a single action. if and while statements are described in more detail in Control Flow.

You can rewrite the possibleNumber example from the Optionals section to use optional binding rather than forced unwrapping:

  1. if let actualNumber = Int(possibleNumber) {
  2. print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")
  3. } else {
  4. print("\"\(possibleNumber)\" could not be converted to an integer")
  5. }
  6. // Prints ""123" has an integer value of 123"

Implicitly Unwrapped Optionals : 

As described above, optionals indicate that a constant or variable is allowed to have “no value”. Optionals can be checked with an if statement to see if a value exists, and can be conditionally unwrapped with optional binding to access the optional’s value if it does exist.

Sometimes it is clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it is useful to remove the need to check and unwrap the optional’s value every time it is accessed, because it can be safely assumed to have a value all of the time.


An implicitly unwrapped optional is a normal optional behind the scenes, but can also be used like a nonoptional value, without the need to unwrap the optional value each time it is accessed. The following example shows the difference in behavior between an optional string and an implicitly unwrapped optional string when accessing their wrapped value as an explicit String:


  1. let possibleString: String? = "An optional string."
  2. let forcedString: String = possibleString! // requires an exclamation mark
  3. let assumedString: String! = "An implicitly unwrapped optional string."
  4. let implicitString: String = assumedString // no need for an exclamation mark

You can think of an implicitly unwrapped optional as giving permission for the optional to be unwrapped automatically whenever it is used. Rather than placing an exclamation mark after the optional’s name each time you use it, you place an exclamation mark after the optional’s type when you declare it.

Error Handling : 

You use error handling to respond to error conditions your program may encounter during execution.


Swift automatically propagates errors out of their current scope until they are handled by a catch clause.


  1. do {
  2. try canThrowAnError()
  3. // no error was thrown
  4. } catch {
  5. // an error was thrown
  6. }

do statement creates a new containing scope, which allows errors to be propagated to one or more catchclauses.

Debugging with Assertions : 

An assertion is a runtime check that a Boolean condition definitely evaluates to true. Literally put, an assertion “asserts” that a condition is true. You use an assertion to make sure that an essential condition is satisfied before executing any further code. If the condition evaluates to true, code execution continues as usual; if the condition evaluates to false, code execution ends, and your app is terminated.

If your code triggers an assertion while running in a debug environment, such as when you build and run an app in Xcode, you can see exactly where the invalid state occurred and query the state of your app at the time that the assertion was triggered. An assertion also lets you provide a suitable debug message as to the nature of the assert.


  1. let age = -3
  2. assert(age >= 0, "A person's age cannot be less than zero")
  3. // this causes the assertion to trigger, because age is not >= 0

In this example, code execution will continue only if age >= 0 evaluates to true, that is, if the value of age is non-negative. If the value of age is negative, as in the code above, then age >= 0 evaluates to false, and the assertion is triggered, terminating the application.

When to Use Assertions

Use an assertion whenever a condition has the potential to be false, but must definitely be true in order for your code to continue execution. Suitable scenarios for an assertion check include:

  • 1. An integer subscript index is passed to a custom subscript implementation, but the subscript index value could be too low or too high.
  • 2. A value is passed to a function, but an invalid value means that the function cannot fulfill its task.
  • 3. An optional value is currently nil, but a non-nil value is essential for subsequent code to execute successfully.


Comments

Post a Comment

Popular posts from this blog

iOS Architecture

Property vs Instance Variable (iVar) in Objective-c [Small Concept but Great Understanding..]

setNeedsLayout vs layoutIfNeeded Explained