Book Image

Swift 4 Programming Cookbook

Book Image

Swift 4 Programming Cookbook

Overview of this book

Swift 4 is an exciting, multi-platform, general-purpose programming language. Being open source, modern and easy to use has made Swift one of the fastest growing programming languages. If you interested in exploring it, then this book is what you need. The book begins with an introduction to the basic building blocks of Swift 4, its syntax and the functionalities of Swift constructs. Then, introduces you to Apple's Xcode 9 IDE and Swift Playgrounds, which provide an ideal platform to write, execute, and debug the codes thus initiating your development process. Next, you'll learn to bundle variables into tuples, set order to your data with an array, store key-value pairs with dictionaries and you'll learn how to use the property observers. Later, explore the decision-making and control structures in Swift and learn how to handle errors in Swift 4. Then you'll, examine the advanced features of Swift, generics and operators, and then explore the functionalities outside of the standard library, provided by frameworks such as Foundation and UIKit. Also, you'll explore advanced features of Swift Playgrounds. At the end of the book, you'll learn server-side programming aspect of Swift 4 and see how to run Swift on Linux and then investigate Vapor, one of the most popular server-side frameworks for Swift.
Table of Contents (9 chapters)

Functions

Functions are a building block of almost all programming languages, allowing functionality to be defined and reused. Swift's syntax provides an expressive way to define your functions, creating concise and readable code.

How to do it...

Let's look at how functions are defined in Swift:

func nameOfFunction(parameterLabel1 parameter1: ParameterType1, parameterLabel2 parameter2: ParameterType2,...) -> OutputType { 

// Function's implementaion
// If the function has an output type,
// the function must return a valid value
return output
}

Let's look at this in more detail to see how a function is defined:

  • func : This indicates that you are declaring a function.
  • nameOfFunction : This will be the name of your function, and by convention is written in camel case (this means that each word, apart from the first, is capitalized and all spaces are removed). This should describe what the function does, and should provide some context to the value returned by the function, if one is returned. This will be how you will invoke the method from elsewhere in your code, so bear that in mind when naming it.
  • parameterLabel1 parameter1: ParameterType1 : This is the first input, or parameter, into the function. You can specify as many parameters as you like, separated by commas. Each parameter has a parameter name (parameter1) and type (ParameterType1); the parameter name is how the value of the parameter will be made available to your function's implementation. You can optionally provide a parameter label in front of the parameter name (parameterLabel1 ), which will be used to label the parameter when your function is used (at the call site).
  • -> OutputType : This indicates that the function returns a value and indicates the type of that value. If no value will be returned, this can be omitted. In the following code illustration, the curly brackets indicate the start and end of the function's implementation; anything within them will be executed when the function is called:
{  
// Function's implementaion
}
  • return output : If the function returns a value, you type return and then the value to return. This ends the execution of the function; any code written after the return statement is not executed.

Now, let's put this into action.

How it works...

Imagine that we are building a contacts app to hold the details of your family and friends, and we want to create a string of a contact's full name. Let's explore some of the ways functions can be used:

// Input parameters and output 
func fullName(givenName: String, middleName: String, familyName: String) -> String {
return "\(givenName) \(middleName) \(familyName)"
}

The preceding function takes three string parameters and outputs a string that puts all these together with spaces in between and returns the resulting string. The only thing this function does is take some inputs and produce an output without causing any side effects; this type of function is often called a pure function. To call this function, we enter the name of the function followed by the input parameters within () brackets, where each parameter value is preceded by its label:

let myFullName = fullName(givenName: "Keith", middleName: "David", familyName: "Moon") 
print(myFullName) // Keith David Moon

Since the function returns a value, we can assign the output of this function to a constant or a variable, just like any other expression:

// Input parameters, with a side effect and no output 
func printFullName(givenName: String, middleName: String, familyName: String) {
print("\(givenName) \(middleName) \(familyName)")
}

The next function takes the same input parameters, but its goal is not to return a value. Instead, it prints out the parameters as one string separated by spaces:

printFullName(givenName: "Keith", middleName: "David", familyName: "Moon") 

We can call this function in the same way as the preceding function, although it can't be assigned to anything since it doesn't have a return value:

// No inputs, with an output 
func authorsFullName() -> String {
return fullName(givenName: "Keith", middleName: "David", familyName: "Moon")
}

The preceding function takes no parameters as everything it needs to perform its task is contained within it, although it does output a string. This function calls the fullName function we defined earlier, taking advantage of its ability to produce a full name when given the component names; reusing is the most useful feature that functions provide:

let authorOfThisBook = authorsFullName()

Since authorsFullName takes no parameters, we can execute it by entering the function name followed by empty brackets (), and since it returns a value, we can assign the outcome of authorsFullName to a variable:

// No inputs, no ouput 
func printAuthorsFullName() {
let author = authorsFullName()
print(author)
}

Our final example takes no parameters and returns no value:

printAuthorsFullName()

You can call this function in the same way as the previous functions with no parameters, but there is no return value to assign.

As you can see from the preceding examples, having input parameters and providing an output value are not required when defining a function.

There's more...

Now, let’s look at a couple of ways to make your use of functions more expressive and concise.

Default parameter values

One convenience in Swift is that you can specify default values for parameters, which allows you to omit the parameter when calling. Let's take the preceding example situation, where we are creating a contact app to hold information about our family and friends. Many of your family members are likely to have the same family name as you, so you can set your family name as the default value for that parameter so that you only need specify the family name if it is different from the default.

Let's enter the following code into a playground:

func fullName(givenName: String, middleName: String, familyName: String = "Moon") -> String { 
return "\(givenName) \(middleName) \(familyName)"
}

Defining a default value looks similar to assigning a value to the familyName: String = "Moon" parameter. When calling the function, the parameter with the default value does not have to be given:

let keith = fullName(givenName: "Keith", middleName: "David") 
let alissa = fullName(givenName: "Alissa", middleName: "May")
let laura = fullName(givenName: "Laura", middleName: "May", familyName: "Jones")
print(keith) // Keith David Moon
print(alissa) // Alissa May Moon
print(laura) // Laura May Jones

Parameter overloading

Unlike Objective-C, Swift supports parameter overloading, which allows for functions to have the same name and only be differentiated by the parameters that they take.

Let's learn more about parameter overloading by entering the following code into a playground:

func combine(_ givenName: String, _ familyName: String) -> String { 
return "\(givenName) \(familyName)"
}

func combine(_ integer1: Int, _ integer2: Int) -> Int {
return integer1+integer2
}

let combinedString = combine("Finnley", "Moon")
let combinedInt = combine(5, 10)
print(combinedString) // Finnley Moon
print(combinedInt) // 15

Both the preceding functions have the name combine, but one takes two Strings as parameters and the other takes two Ints. Therefore, when we come to call the function, the compiler knows which implementation we intended by the values we pass as parameters.

We've introduced something new in the preceding function declarations--anonymous parameter labels, _ givenName: String.

When we declare the parameters, we use an underscore _ for the parameter label; this indicates that we don't want a parameter name shown when calling the function. This should only be used if the purpose of the parameters is clear without the labels, as is the case in the preceding example--combine("Finnley", "Moon").

See also