Find online courses made by experts from around the world.
Take your courses with you and learn anywhere, anytime.
Learn and practice real-world skills and achieve your goals.
Course updated December 2015!
Become one of the world's earliest Swift developers with this introductory course on Apple’s new programming language.
A Modern Language Evolved from Objective C
Swift is a multi-paradigm programming language developed by Apple for use with iOS and OS X. Designed to replace Objective C, work began on Swift in 2010 and the first mobile app was debuted in June 2014 at the Worldwide Developers Conference. Despite its goal of replacing Objective C, Swift is capable of working alongside the more dated Objective C language while using the Cocoa and Cocoa Touch frameworks.
Swift is built with the LLVM compiler included in Xcode 6 beta, and uses the Objective-C runtime, allowing Objective-C, Objective-C++ and Swift code to run within a single program. During it’s debut, Swift was described as “Objective C without the C” by Apple’s VP of Software Engineering Craig Federighi.
Contents and Overview
Through 140+ video lectures and 11 hours of content, you will be lead through setting up Swift locally, the basics of the language, how it compares to other common languages (including Objective C), and how to get started on new projects.
The course is designed to provide a comprehensive introduction to Swift, so that you can begin experimenting right away. Upon completion, you will understand the foundations of Swift code and will be able to develop custom applications. You will also get experience working with Xcode's new .playground file. By enrolling in this course you will be months ahead of other developers attempting learn the new Swift programming language by navigating Apple's 500-page instructional document.
Course material is regularly refreshed to include all of the newest updates and information, and since you’re granted lifetime access upon registering, you can rely on this course to keep your Swift skills on the cutting edge.
Not for you? No problem.
30 day money back guarantee.
Learn on the go.
Desktop, iOS and Android.
Certificate of completion.
|Section 1: Welcome to Class!|
Goals of the ClassPreview
A Brief History of Swift
Playgrounds and Your First Line of Code!
|Section 2: Variables and Constants|
Our First Variable
Variables Can Change
Our First Constant
Constants Don't Change
|Section 3: Strings and Ints|
Floats and Doubles
Mixing Ints and Doubles
|Section 4: Comments and Print|
Single Line Comments
Multi Line Comments
|Section 5: Booleans and If Statements|
Equal, Greater Than, Less Than
|Section 6: Switches|
|Section 7: Arrays|
Getting A Specific Item
Remove and Insert
|Section 8: Dictionaries|
Type and Empty Dictionaries
Adding and Editing
|Section 9: Sets|
Insert and Remove
|Section 10: Loops|
What Loop Are We On?
For Loops and Arrays
For Loops and Dictionaries
Repeat While Loops
|Section 11: Functions|
|Section 12: Optionals|
I'm Nick Walter, an iOS developer that has been focused on mobile app design and creation for over 3 years. My involvement in the iOS community started off with a bang, and in 2013 I was one of 25 students worldwide to be invited to Apple's "Cocoa Camp." Within my community, I am also co-president of an Apple developer group called "Cocoa Heads."
I've always had an itch to make things, but growing up in a small town I had limited access to programming resources. This frustration drove my early interest in online education. After experimenting with various companies, learning styles, and teaching processes, I've adopted the best strategies and used them in my courses. My experience as an online student has directly influenced my teaching style, and I am now proud to help students all over the world with their online learning goals.
Since the announcement of the new Swift programming language by Apple, I have buried myself in the Apple documentation and any online resource that is available. In my first Swift course, I provide students with a detailed explanation of the topics and skills needed to learn Swift, an overview of the basic features of the new language, and get you started to begin building your first products.
Prior to teaching the internet's first course on Swift, I have created 5 iOS apps from scratch that are currently live in the App Store and being used by thousands of users worldwide. Using my experience launching my own apps, I'll walk you through the shortcuts that can save you time and frustration from having to teach yourself.
In Objective C (as well as many other languages), every time a variable is declared and contextually initialized, the type must always be specified. For example:
Swift is a strongly typed language, meaning that the type of a variable must be determined at compilation time and cannot be changed during the variable's lifetime. In many cases, the compiler is able to automatically determine the type from the context, and in those cases specifying the variable type is redundant and can be omitted. This feature is called type inference.
The above code can be literally translated to Swift as:
and can also be rewritten more concisely as:
In the above cases, all variables are initialized with literal values or with new instances whose
respective types are unambiguously determined at compilation time.
Type inference also works with values returned by functions and methods. If we implement a square function working on integers:
We can assign its return value to a variable with no need to specify its type, because it is inferred by the Int return type:
In Swift, it's possible to overload methods in a way not available in many other language:
differing by the return type only.
For example, we could provide a new implementation of the square function defined above, but returning a Double:
Now we've got 2 functions having the same square name, both taking an integer parameter,
but one returning an integer and the other one a double.
The first thing to notice is that type inference for variable declaration no longer works:
That's because the compiler is not able to determine which of the 2 overloads to call. This is one of the rare cases where declaring and initializing a variable requires the type to be specified. So the following 2 cases work:
In both cases, the correct version of the function to invoke is determined by the type of the variable the return value is assigned to. Another way to resolve the ambiguity is by performing an explicit downcast of the return value:
will invoke the version returning an integer, whereas:
will invoke the overload returning a double.
If a new friend name is added to the copy:
it is correctly listed and printed:
but friends still contains the original list:
so without the change. Why is that happening?
Types in swift can be divided into 2 different categories:
Classes and closures fall in the first category, and everything else in the second, which includes:
When a reference type is instantiated and assigned to a variable, a reference to the instance and not the instance itself is assigned to the variable. If we assign a new instance of UIView to a variable:
and next we copy into another variable:
both variables will contain references to the same UIView instance, because the reference to the instance, and not the instance itself is copied. Consequently, any mutating action performed from view1 will be visible from view2 and vice-versa, because the mutation is performed on the same instance.
Different from reference types, when a value type is instantiated and assigned to a variable, the value itself is assigned. So the variable contains the value. A direct consequence is that when the variable is copied, the value, and not a reference to it, is copied. Let's consider the following code:
Intuitively, we know that if int1 is changed int2 will keep its value and won't be affected by the int assignment:
Back to our friends list, arrays (as well dictionaries and sets) in Swift are implemented as structures, which are value types. So when an array assigned to a variable:
is copied into another variable:
a copy of it is created and assigned to the new variable, and each of the two instances will live their own life.
Before thinking that value types are slow and inefficient because every time they are assigned to variables or passed as arguments a copy is created, it's very important to know that the compiler plays an important role here by optimizing their usage. So if an array assigned to a variable a is copied to another variable b, but none of the two instances is mutated, then the compiler is smart enough to avoid creating a copy and manage to have both variables point to the same data.
In development it's frequent to have to transform a list of data into something else, which usually is:
commonly known respectively as filter, map, and reduce.
In Objective C, any of the above transformations can be implemented using a for-each loop. Let's consider the following array of daily temperatures:
One of the possible ways to calculate the average temperature is:
Using the reduce method of Swift arrays instead, the same code can be rewritten as:
The most interesting piece of code is the following:
which calculates the sum of all array elements.
By giving an initial value and a closure taking 2 parameters:
the reduce method iterates over all of its elements, invoking the closure for each element and at the end returning the accumulated value.
In the above case the + function is used - for clarity, it's equivalent to writing:
If we want to convert the array of temperatures from Fahrenheit to Celsius, in Objective C we'd use a for-each loop similarly to the previous case.
In Swift, instead we can use the map method, passing a closure responsible of transforming each element which takes an array element as input and returns the transformed element as output. The map method in turn returns an array of the same length as the original, with the values replaced by the transformed ones:
Note that the original and transformed types don't have to be the same. For instance, it can be a string:
This is the most intuitive of the 3 features, again implementable in Objective C using a for-each loop, but invocable in Swift at the cost of one single call. If we want, for example, to retrieve the subset of temperature above 32:
Why are these 3 methods so important? Because besides simplifying the code when individually used, they can be chained together, performing complex transformations with just a few lines of code.
Let's look at a real example of their usage. We have a User entity, which has an optional email field:
We want to send an email to all users having a valid email address, so we need to extract a list of email addresses from a list of users:
Combining filter with map, that's pretty easy:
The same result is obtained using reduce only, obtained by:
and implemented in either long form:
Consider extending the previous User entity by adding a new hoursWorked property:
which is de-serialized from JSON in string format. We want to iterate over all users and calculate the total number of hours. Since the new property is of string type, it must be converted to integer before being usable for arithmetic calculations. One way to achieve that (the long way) could be done in 5 steps:
A more compact version of the algorithm can be implemented in just 3 steps, with the first 2 shared with the previous method:
A recurrent case in programming is the need of duplicating an algorithm or a type to work with different data types than the original ones, with the duplicated part differing by the types only and not the actual implementation.
Because Swift is a very strongly typed language and there is no explicit conversion, even among types that might intuitively be considered equivalent (like integers, unsigned integers, etc.), having a generic way to implement algorithms and types is very useful.
Generic programming is one of the most useful and powerful features of modern languages, although they have their roots in old languages like lisp and ada (old doesn't necessarily means obsolete), and it's probably one of the most awaited feature in Objective C, although never brought to life.
Generics is a very complex topic which cannot be described in just a few paragraphs. Let's take a look at 2 simple examples, a generic function and a generic data type.
A very simple example showing how to benefit from using generics is a function returning the minimum of two values passed as arguments:
This implementation works for integers only:
but it cannot be used, for instance, with 2 unsigned integers:
Cannot invoke '_min' with an argument list of type '(UInt, UInt)'
The solution consists of making the function generic by specifying a type T in the function signature, and constraining it to adopt the Comparable protocol:
The Comparable protocol is adopted by all types for which the less than and equal to comparison operators are defined, and of course any user-defined type can adopt that protocol. With the new generic implementation, all of these cases work:
as well as any other case using a data type implementing the Comparable protocol.
A data structure is used to group a set of related data together with the purpose of being used in an efficient way. There are several data structures we use every day, like arrays, dictionaries, sets, queues, and so forth.
Although a specific data structure can be implemented to work with a specific data type only, data structures are perfect candidates for being generics. So to be able to store data of any type, with the only constraint that an instance of a data structure must contain elements of the same type.
Swift already provides generic Array, Dictionary and Set structures. We'll take a look at a
custom stackimplementation instead.
A stack is a data structure where elements can be pushed at the top of the stack and popped from the top. It is usually referred to as last in, first out, or LIFO for short, because the first element extracted at any time is the one that's been inserted last and not previously extracted yet.
A good real-world comparative example is a stack of dishes: the last dish stacked up is most likely the first that is removed from the stack.
For its implementation, we'll be using a Node class:
The stack itself is implemented as follows:
The head property always points to the last node added to the stack. When pushing an element, a new node is created, containing the element to store and the reference to the currenthead, and it is set as the new head of the stack.
The pop method instead checks if the head contains a value, in which case it removes the node from the head and then returns its element. Removing a node from the head consists of replacing the head property with the node referenced by the nextElement property of the removed node, which can be nil if there's no element left in the stack.
Using the stack is pretty simple: values are stacked up using push, and removed using pop:
In Objective C, classes are reference types, which means that they are assigned and passed by reference and not by value. For instance, when a string is created we are used to writing code like:
Since the string variable is a reference, when it is nil it means it doesn't point to any instance
- it lacks a value. So, checking if a reference points to an instance can be simply done with a logical expression like:
Similarly, to check if a variable doesn't reference any instance:
When it's about value types instead, it's a problem, because there is no special value indicating the lack of a value.
A common pattern is to label an unused value in the spectrum of all possible values - think for example at theselectedSegmentIndex property of UISegmentedControl, which by convention uses the -1 value to indicate absence of selection. Whereas this workaround may work for numbers, it doesn't for types with a restricted set of possible values (such as a boolean) or structures.
As an attempt to fix this problem, Swift introduces optionals, used to indicate the absence of
value for either value and reference types.
Optionals is conceptually a very simple topic, but in reality it can be very complex if not completely understood.
One important thing to never to be forgotten, is that an optional is implemented as a generic enumeration:
However, since optionals are frequently used, their usage is made less verbose by providing some syntactic sugar. Statements at the left side of the following table and the corresponding at the right are equivalent.
It's important to remember that a variable declared as optional is of an enum type and not of the value it contains- this helps prevent several headaches caused by improper usage of optionals. When the enum holds a value, it is stored as the associated value of the .Some enum case.
The action of storing a value into an optional variable is usually referred to as wrapping, whereas the opposite action is unwrapping. These terms help with remembering that an optional variable is not the value it contains. An optional variable can be thought as a box, which can be empty (nil = .None = absence of value) or can contain something. In order to use the "something", it must be unwrapped from the box first.
To understand this concept, let's look at a simple example. We can sum 2 Int variables:
but we cannot sum 2 optional Int variables:
Value of optional type 'Int?' not unwrapped: did you mean to use '!' or '?'?
We can sum the values unwrapped from optional variables though, using either optional binding:
or forced unwrapping (which is highly discouraged, except for a restricted number of cases):
The let unwrappedVar = optionalVar syntax is called optional binding when used in an if statement, and consists of:
if optionalVar contains a value:
unwrapping a value from optionalVar
assigning it to the implicitly declared unwrappedVar variable, (having the same type of the unwrapped value)
evaluating to true
otherwise, if optionalVar doesn't contain a value (i.e. it's nil):
The syntactic sugar uses ? and ! as both operators and modifiers, depending on the context they are used in:
Remember that both the ! operator and modifier are very dangerous when improperly used, because:
The last topic covered in this quick intro to optionals is optional chaining. Consider the following structure:
where the emails property is an optional array of String. If we declare an optional variable of User type:
and later in our code we want to retrieve the first email address, we'd need to use optional binding to extract the user first and the array later:
which is equivalent to:
Using optional chaining instead, we can use the ? operator to unwrap a value from an optional (if any) - in case of anil value the expression evaluation stops and resolves to nil. Multiple unwraps can be performed in the same statement, and the expression is fully evaluated and executed if all unwraps succeed. Basing on this new knowledge, the previous code can be rewritten as:
If either user or emails is nil, the expression evaluates to nil. Otherwise the value of first is
Note that optional chaining can be used for both properties and methods. For example, to add a new email address the following expression can be used:
The append method is invoked only if the preceding expression evaluates to a non-nil value, otherwise it is skipped and nothing occurs.
Everybody knows that in Objective C, functions and methods can return one value only, which can either be a basic data type (including enums and blocks) or an instance of a class. A function returning more than one value has to either:
The latter is commonly used, even in several foundation APIs, such as the error parameter in the following static method from NSData:
Of course in Swift the same pattern can be used, and in fact the corresponding counterpart of the above method is:
Note: The case of NSError as the 2nd return value, very frequently used in almost all iOS/MacOS frameworks, can alternatively and more efficiently be implemented in swift using enumerations. See tip #7.
This case is an example of an API, which for obvious reasons we cannot change. However, when developing our own code, we have at our disposal a very useful tool allowing the creation of anonymous structures called
A tuple, which is a value type, is a list of typed values optionally named and enclosed in parentheses:
A function returning the min and max values from a list of temperatures can be implemented as:
As a tuple is a value type on its own, it can be used as any other value type, including an array data type:
Looking at a function declaration:
the list of parameters looks like a tuple. Well, it's actually a tuple - we can invoke the _min function as either:
Note: in order for a tuple to be passed in place of the list of a function/method parameters, the tuple itself must be immutable (i.e. declared using let and not var).
Consider the following Objective C method:
which is supposed to return an array of posts if the call succeeds, otherwise it returns an error via the reference variable error.
For every invocation, one of the 2 return values is not used:
In Swift, any switch case can have one or more associated values whose types are defined in the case declaration. Note that associated values are not statically assigned to the enumeration cases, just their types are.
In our case, we need 2 cases with an array associated to the Success case and an NSError associated to theFailure case:
Before diving into looking at how to use this enumeration, let's make it more generic so it can be reused for other types. The above code defines the Result enumeration to work with the Array < Post > type only, but that type can be made generic, enabling the Result enumeration to work with any type:
Unfortunately, the code as written above doesn't compile because Swift doesn't support generic associated values if there is at least another case using associated values. The solution is to box the generic value into a class:
and then use Box < T > as the associated type:
With this new tool in our bag, the retrievePostsWithError method can be redefined in Swift as:
and invoked like:
Everybody has written blocks in Objective C, and everybody has at least once wondered what's the correct syntax to use depending on the context.
The Swift counterpart of the Objective C block is the closure. A closure is an unnamed and self contained block of code which falls under the category of reference types, so it can be assigned to variables, passed to functions as argument, and so on - and of course it can also be executed.
The syntax to create a closure and assign to a variable is pretty simple:
The closure signature is specified in the same way as in functions, and the in keyword separates the signature from the implementation. Everything is enclosed in curly braces. It can be invoked as if it were a function:
Although closures can be thought as a subset of functions, in reality it's the opposite: functions are a special case of closures.
The good parts about Swift closures vs. Objective C blocks is in their syntax: very clean, easy to remember, and can be optimized/simplified depending on the context. For example, omitting the input and output types when they can be inferred, and using shorthand arguments and implicit returns for single statements.
But what's probably the most useful simplification is the trailing closure syntax: when a closure is passed as the last argument of a function or method, it can be written outside of the parenthesis, and without the external parameter name (if any). For example, the well known animateWithDuration can be invoked as:
Being closures treated as any other data type, they can also be stored in a data structure to be executed at a later time and without any limit to the number of times they can be invoked.
It's relatively straightforward to implement a very simple instantiator, where using a declarative method, a type is bound to a closure which creates and returns an instance of that type.
The first step is to define an Instantiable protocol with a parameter-less initializer only, which all registrable types must implement:
and a closure alias taking no parameter and returning an instance of a type implementing that protocol:
The instantiator implementation would look like:
The register method, given a type and a closure stores the initialization closure in the invokers dictionary, using as key the string representation of the type.
The instantiate method instead, given a type, retrieves the corresponding initialization closure from the dictionary (if found) and invokes it; otherwise, it returns .None (which is equivalent to saying nil).
Some use cases:
This simple example binds a type to a closure creating an instance of the same type - however, it can be extended to work similarly to a dependency injection container, with a protocol used as key, bound to a class implementing it.
When the execution flow has to go through one of multiple paths depending on a value, Objective C's switchstatement comes into help:
The biggest limitation is that it works with ordinal types only (integer, unsigned integer, boolean, enumerations, etc.) - other types (strings, double, strings, classes, etc.) are not supported. In those cases a multiple if/else if statement must be used:
Fortunately, in Swift the switch statement has been supercharged. It can be used with almost any type, including strings, floating point numbers, reference types, and so forth. But there's a lot more.
First of all, there are some differences that are often seen as limitations compared to the Objective C counterpart:
There is no implicit fall through. In Objective C, if a case doesn't end with a break statement, execution continues to the next case's body. In Swift instead the break statement is always implicit.
The cases list must be exhaustive: any possible value must be handled by at least one case As described in tip tip #7 , an enumeration can have associated values to one or more of its cases. For instance, the optional enumeration:
has an associated value of generic type T bound to the Some case. Associated values can be easily extracted from a case using a switch statement:
It also works with cases handling multiple values, ranges, tuples and conditions:
Apple put in a lot of effort to make the 2 languages work together. It's a must have when a very strongly typed language like Swift meets a not-so-much strongly typed like Objective C and a large number of frameworks entirely written using it.
To date no framework is implemented, either partially or fully using the Swift language. Including new ones, like the ResearchKit Framework , which is 100% Objective C and whose development started after Swift was released. Apparently there's a limitation in the language that prevents it from being used for system frameworks, but this is likely going to change in the future.
Below are some Q&A's about using Objective C and Swift:
Can I use Swift in an Objective C project?
Yes. Create or add a new Swift file to the project, and it will compile without any problem.
How do I access Objective C code from Swift?
When the first Swift file is added to or created in an Objective C project, Xcode will prompt to create abridging header
which is merely a header file, initially empty, but with a special function: all #imports will automatically be bridged to Swift.
So if we have an Objective C ViewController class, defined in the ViewController.h header file, simply adding the #include statement to the bridging header the class (and whatever is defined in that header) will automatically be accessible from Swift: #include "ViewController.h"
How do I access Swift code from Objective C?
Xcode automatically creates Objective C wrappers for compatible Swift code, stored in the < project-name >-Swift.h, where < project-name > is the actual project (module) name. To access Swift types from Objective C, simply import the mentioned header file: #import "< project-name >-Swift.h"
Note: the Swift header is not listed in the project navigator, but it can be opened by cmd+clicking its name in an import statement. Since it is automatically generated, any change made to the file will be lost at the next compilation.
Is there any Swift code that is not compatible with Objective C?
Yes, several Swift features are not compatible with Objective C. A non exhaustive list includes:
I'm trying to use Swift code in an Objective C project. I'm importing the Swift header file, but the following error is reported by the compiler:
"< project-name >-Swift.h" file not found
Why is that happening?
Most likely there is a circular reference, which happens when an Objective header file is imported in the bridging header, and either the header file itself or its implementation imports the Swift header. For example:
@interface ViewController : UIViewController
The ViewController class is exposed to Swift, because its header is included in the bridging
header, but the Swift header is also imported in its header file, causing a circular reference.
To prevent circular references, it might be useful to know that:
Objective C code should not be exposed to Swift if it depends on other Swift code classes that must be exposed to Objective C, and depend from Objective C code, should not be implemented in Swift
This tutorial was made in collaboration with TopTal.