Mastering Swift 5
Rate it:
Open Preview
Started reading April 19, 2020
7%
Flag icon
Swift 3, which was released in 2016, was a major enhancement to the Swift language that was not source-compatible with previous releases of the Swift language.
7%
Flag icon
One of the main goals of Swift 3 was to be source-compatible across all platforms, so the code that was written for one platform would be compatible with all other platforms. This means that the code we develop for macOS should work on Linux.
7%
Flag icon
In September 2017, Swift 4 was released. One of the primary goals of the Swift 4 compiler is to be source-compatible with Swift 3. This will allow us to compile both Swift 3...
This highlight has been truncated due to consecutive passage length restrictions.
7%
Flag icon
One of the original goals of Swift 4 was to stabilize the Swift Application Binary Interface (ABI). The main benefit of a stable ABI is to allow us to distribute frameworks in a binary format across multiple versions of Swift. If a stable ABI is in place, we would be able to build a framework with the Swift 4 compiler and have it work with applications that were written in future versions of Swift.
7%
Flag icon
A stable ABI means that a library that is compiled for one version of Swift, let's say Swift 5, will theoretically work with future versions of Swift without having to be recompiled.
7%
Flag icon
The development of Swift was started in 2010 by Chris Lattner.
7%
Flag icon
There are a lot of similarities between Swift and Objective-C. Swift adopts the readability of Objective-C's named parameters and dynamic object model.
7%
Flag icon
dynamic object model, we are referring to the ability for types to change at runtime.
7%
Flag icon
Objective-C is a superset of C and provides object-oriented capabilities and a dynamic runtime to the C language.
10%
Flag icon
For style purposes, it is strongly recommended that you do not use semicolons in your Swift code. If you are really set on using semicolons, be consistent and use them on every line of code; however, there is no warning if you forget them.
10%
Flag icon
For style purposes, it is recommended that you do not include parentheses in your code unless you have multiple conditional statements on the same line. For readability purposes, it is good practice to put parentheses around the individual conditional statements that are on the same line.
10%
Flag icon
These bugs could have also been prevented by other means, such as unit testing and code reviews, but requiring developers to use curly brackets, in my opinion, is a good security standard.
10%
Flag icon
This is another safety feature built into Swift. It prevents the developer from forgetting the second equals sign (=) in a comparison statement.
11%
Flag icon
Constants and variables associate an identifier (such as myName or currentTemperature) with a value of a particular type (such as the String or Integer type), where the identifier can be used to retrieve the value. The difference between a constant and a variable is that a variable can be updated or changed, while a constant cannot be changed once a value is assigned to it.
11%
Flag icon
The use of constants is encouraged in Swift. If we do not expect or want a value to change, we should declare it as a constant. This adds a very important safety constraint to our code that ensures that the value never changes.
11%
Flag icon
Type inference allows us to omit the variable type when the variable is defined with an initial value.
12%
Flag icon
Unless there is a specific reason to define the size of an integer, I would recommend using the standard Int or UInt types.
13%
Flag icon
One of the new features of Swift 5 is the isMultiple(of:) method, which was added to the integer type. This method allows us to check if one number is the multiple of another number.
14%
Flag icon
We can also retrieve substrings and individual characters from our strings; however, when we retrieve a substring from a string, the substring is an instance of the Substring type and not the String type.
15%
Flag icon
Tuples group multiple values into a single compound type. These values are not required to be of the same type.
15%
Flag icon
Enumerations (also known as enums) are a special data type that enables us to group related types together and use them in a type-safe manner.
16%
Flag icon
If integers are used for the raw values of an enumeration, then we do not have to assign a value to each member. If no value is present, the raw values will be auto-incremented.
18%
Flag icon
It is very important to understand that nil in Swift is very different from nil in Objective- C or other C-based languages. In these languages, nil is a pointer to a non-existent object; however, in Swift a nil value is the absence of a value. This concept is very important to fully understand optionals in Swift.
18%
Flag icon
The optional type is an enumeration with two possible values, None and Some(T), where T is the generic associated value of the appropriate type.
19%
Flag icon
With optionals, Swift is able to detect problems such as this at compile-time and alert us before it becomes a runtime issue.
19%
Flag icon
To unwrap or retrieve the value of an optional, we place an exclamation mark (!) after the variable name.
19%
Flag icon
Optional binding is the recommended way to unwrap an optional. With optional binding, we perform a check to see whether the optional contains a valid value and, if so, unwrap it into a temporary variable or constant. This is all performed in one step.
20%
Flag icon
Arrays store data in an ordered collection, sets are unordered collections of unique values, and dictionaries are unordered collections of key-value pairs.
75%
Flag icon
Concurrency is the concept of multiple tasks starting, running, and completing within the same time period.
75%
Flag icon
In fact, in order for tasks to be run simultaneously, our application needs to be running on a multicore or multiprocessor system.
75%
Flag icon
Parallelism is the concept of two or more tasks running simultaneously.
75%
Flag icon
In order to understand the difference between concurrency and parallelism, let's look at how a juggler juggles balls. If you watch a juggler, it seems they are catching and throwing multiple balls at any given time, however, a closer look reveals that they are, in fact, only catching and throwing one ball at a time. The other balls are in the air waiting to be caught and thrown. If we want to be able to catch and throw multiple balls simultaneously, we need to have multiple jugglers.
75%
Flag icon
Traditionally, the way applications added concurrency was to create multiple threads;
75%
Flag icon
The biggest problem with using threads was that our applications ran on a variety of systems (and processors), and in order to optimize our code, we needed to know how many cores/processors could be efficiently used at a given time, which is usually not known at the time of development.
75%
Flag icon
An asynchronous function typically starts the long running task and then returns prior to the task's completion. Usually, this task runs in the background and uses a callback function (such as closure in Swift) when the task completes.
75%
Flag icon
The queues manage these submitted tasks and execute them in a First-In, First-Out (FIFO) order. This ensures that the tasks are started in the order they were submitted.
76%
Flag icon
The system can scale the number of threads dynamically, based on the overall available resources of the system and the current system conditions. This means that dispatch queues can manage the threads with greater efficiency than we could.
76%
Flag icon
It is recommended that we use a reverse DNS naming convention. This parameter is optional and can be nil.
76%
Flag icon
A concurrent queue will execute the tasks in a FIFO order; however, the tasks will execute concurrently and finish in any order.
76%
Flag icon
This shorthand version is how we usually submit small code blocks to our queues. If we have larger tasks or tasks that we need to submit multiple times, we will generally want to create a closure and submit the closure to the queue as we showed in the first example.
77%
Flag icon
A serial queue functions a little different than a concurrent queue. A serial queue will only execute one task at a time and will wait for one task to complete before starting the next one.
78%
Flag icon
The main queue is automatically created for the main thread when the application starts. This main queue is a serial queue; therefore, items in this queue are executed one at a time, in the order that they were submitted. We will generally want to avoid using this queue unless we have a need to update the user interface from a background thread.
78%
Flag icon
Operation queues are part of the Foundation framework and function like dispatch queues as they are a higher-level of abstraction over GCD.
78%
Flag icon
An operation represents a single unit of work or task. The Operation type is an abstract class that provides a thread-safe structure for modeling the state, priority, and dependencies.
78%
Flag icon
class must be subclassed
78%
Flag icon
Apple provides a concrete implementation of the Operation type that we can use as-is for situations where it does not make sense to build a custom subclass. This subclass is BlockOperation.
78%
Flag icon
More than one operation queue can exist at the same time, and, in fact, there is always at least one operation queue running. This operation queue is known as the main queue. The main queue is automatically created for the main thread when the application starts and is where all of the UI operations are performed.
78%
Flag icon
The BlockOperation class is a concrete implementation of the Operation type that can manage the execution of one or more blocks. This class can be used to execute several tasks at once without the need to create separate operations for each task.
78%
Flag icon
One of the differences between dispatch queues and operations is that, with dispatch queues, if resources are
78%
Flag icon
available, the tasks are executed as they are added to the queue. With operations, the individual tasks are not executed until the operation itself is submitted to an operation queue. This allows us to initiate all of the operations into a single block operation prior to executing them.