Tuples
A rather powerful aspect of Swift is that function return types (and constants/variables) can include a combination of values into a single value. These combinations are called tuples. Here's an example of an unnamed tuple:
let http503Error = (503, "Service Unavailable")
Here's a tuple used as a return type in a function direct from Apple's Swift documentation. Observe how it uses much of what we've learned thus far:
func minMax(array: [Int]) -> (min: Int, max: Int) { var currentMin = array[0] var currentMax = array[0] for value in array[1..<array.count] { if value < currentMin { currentMin = value } else if value > currentMax { currentMax = value } } return (currentMin, currentMax) } Excerpt From: Apple Inc. "IOS Developer Library". https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID164
Classes
In OOP, classes make up the basic frame of an object, its functionality and interactions with other classes, objects, and various data structures, such as protocols, Structs, extensions, generics, and enumerations. In the following chapters, as we begin to structure our games, we will dive deeper into all of these concepts, but for now, let's understand the basics of classes and how they differ in Swift from Objective-C and other languages.
Here's the basic structure of a class in Swift:
//(a) Global-project wide properties/variables //(b) class className : parentClassName, protocolName…protocolnName { //(c) class scope properties //(d) initializers (init(), convenience, required, etc) //(e) func function_name1(argumentName1 : argumentType1, argumentName2 : argumentType2, argumentNameN : argumentTypeN) -> return_type { function-scope variables and body } . . . func function_nameN(argumentName1 : argumentType1, argumentName2 : argumentType2, argumentNameN : argumentTypeN) -> return_type { function-scope variables and body } //(f) deinit() } // end of the class //(g) global-project wide properties/variables (alternative position)
The Swift class structure works somewhat similar to what we see in C# and Java, as opposed to Objective-C's two files' (.h
/header
, .m
/.mm
/ implementation) setup:
(a)
: We can have properties (like variables, constants, Structs, and enums) outside of the class declaration, which would make them global in scope, aka accessible throughout the entire project/game/app.(b)
: This is the actual class represented by what we named our.swift
file. Again, this is different from Objective-C'sclassname.h - classname.m/.mm
dual file setup for a single class. A class can be a child class of another class. We don't have to declare a parent/base class in Swift. Classes we make can be their own base classes. We can make classes as Objective-C classes by subclassing them from NSObject. The benefit of that is getting Objective-C runtime metadata and capabilities, but we take a hit in performance from the extra baggage. Either in the same place as theparentClass
or after the colon:
ofparentClass
, we can declare which protocols this class will adhere to. We'll discuss more on protocols later in the book, but just think of them as making sure your class utilizes the same functions as the protocol dictates.(c)
: These are where we'd place variables, constants, Structs, enums, and objects that are relevant for use in the scope of the class.(d)
: Initializers are special functions we use to set up the properties in section(c)
when other classes and data structures use instances of the class viaclassName(initializer parameters)
. We will discuss more on initializers more in the next chapter as we structure our games. They don't have to be at the top of the class, but it's a good practice to do so.(e)
: These are where your class functions will be declared and developed. We can have functions that are known as class functions. These are designated with the keywordsclass func
. In short, class functions are part of the class as a whole as opposed to an instance of the class. It's best practice to place these above the next, more common type of function, the public functions, that can be accessed by other classes and properties via the dot operator (that is,className.function(parameters)
). Using theprivate func
keywords, as in C# and Java, we can create private functions that are only accessible to the class's own functions and properties.(f)
: Thedeinit()
function is a special optional function that deals with how we clean up the data allocated by our class with memory management and eliminating what's known as memory leaks. Apple's ARC (Automated Reference Counting) handles most of this, but there are key words, such as weak and unowned, that we will at times have to put before various properties to make sure that they don't hang around after use.This is a rather involved topic, but worth looking into to avoid memory leaks in your game. ARC does take care of most of this, but there might be objects in your game that could potentially hang around. It's highly recommended to read Apple's own documentation on this topic, as memory management in iOS is always in the evolving stage. You can view the full documentation on ARC and memory management in Swift at https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html.
(g)
: If we wish, we can have global properties also at the bottom of our.swift
files, after the end of the class declaration. Apple's own game example, Adventure (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html), places global properties in this spot.