Book Image

Swift: Developing iOS Applications

By : Jon Hoffman, Andrew J Wagner, Giordano Scalzo
Book Image

Swift: Developing iOS Applications

By: Jon Hoffman, Andrew J Wagner, Giordano Scalzo

Overview of this book

The Swift––Developing iOS Applications course will take you on a journey to become an efficient iOS and OS X developer, with the latest trending topic in town. Right from the basics to the advanced level topics, this course would cover everything in detail. We’ll embark our journey by dividing the learning path into four modules. Each of these modules are a mini course in their own right; and as you complete each one, you’ll gain key skills and be ready for the material in the next module. The first module is like a step-by-step guide to programming in Swift 2. Each topic is separated into compressible sections that are full of practical examples and easy-to-understand explanations. Each section builds on the previous topics, so you can develop a proficient and comprehensive understanding of app development in Swift 2. By the end of this module, you’ll have a basic understanding of Swift 2 and its functionalities. The second module will be the an easy-to-follow guide filled with tutorials to show you how to build real-world apps. The difficulty and complexity level increases chapter by chapter. Each chapter is dedicated to build a new app, beginning from a basic and unstyled app through to a full 3D game. The last two chapters show you how to build a complete client-server e-commerce app right from scratch. By the end of these modules, you’ll be able to build well-designed apps, effectively use AutoLayout, develop videogames, and build server apps. The third and the last module of our course will take an example-based approach where each concept covered is supported by example code to not only give you a good understanding of the concept, but also to demonstrate how to properly implement it.
Table of Contents (6 chapters)
4
A. Biblography
5
Index

Unless you are on the cutting edge of computer science, most of the software you write will be more focused on user experience and maintainability than on any particular advanced programming language. As you write more and more of this type of software, you will see a lot of patterns emerge, especially if you focus on readability and maintainability, as most of us should. However, we don't have to come up with all of these patterns on our own; people have been programming and coming up with patterns for years that transfer really well from language to language.

We call these patterns, design patterns. Design patterns is a massive topic with countless books, tutorials, and other resources. We spend our entire careers practicing, shaping, and perfecting the use of these patterns in practical ways. We give each pattern a name so that we can have smoother conversations with fellow programmers and also organize them better in our own minds.

In this chapter, we will take a look at some of the most common design patterns, especially the ones important to understand Apple's frameworks. You will have a much easier time understanding and making use of that code when you begin to recognize patterns while using other people's code. It will also help you write better code yourself. We will focus on the high level ideas behind each pattern and then how to implement them in Swift. We will then go past the classic design patterns and look at some advanced features of Swift that allow us to write particularly clean code.

To do all that, we will cover the following topics in this chapter:

Let's delve a little deeper into what a design pattern is before we dive into the specific patterns. As you may have begun to understand, there are unlimited ways to write a program that does even a simple thing. A design pattern is a solution to solve a recurrent and common problem. These problems are often so ubiquitous, that even if you don't use a pattern deliberately, you will almost certainly be using one or more patterns inadvertently; especially, if you are using third-party code.

To better evaluate the use of design patterns, we will look at three high-level measurements: coupling, cohesion, and complexity.

Coupling is the degree to which individual code components depend on other components. We want to reduce the coupling in our code so that all our code components operate as independently as possible. We want to be able to look at them and understand each component on its own without needing a full understanding of the entire system. Low coupling also allows us to make changes to one component without drastically affecting the rest of the code.

Cohesion is a reference to how well different code components fit together. We want code components that can operate independently, but they should still fit together with other components in a cohesive and understandable way. This means that to have low coupling and high cohesion, we want code components that are designed to have a single purpose and a small interface to the rest of our code. This applies to every level of our code, from how the different sections of our app fit together, down to how functions interact with each other.

Both of these measurements have a high impact on our final measurement: complexity. Complexity is basically just how difficult it is to understand the code, especially when it comes to practical things like adding new features or fixing bugs. By having low coupling and high cohesion, we will generally be writing much less complex code. However, taken to their extremes, these principles can sometimes actually cause greater complexity. Sometimes the simplest solution is the quickest and most effective one because we don't want to get bogged down into architecting the perfect solution when we can implement a near perfect solution ten times faster. Most of us cannot afford to code on an unlimited budget.

Instead of having a single giant list, design patterns are usually organized according to how they are used into three main categories: behavioral, structural, and creational.

Behavioral patterns are patterns that describe how objects will communicate with each other. In other words, it is how one object will send information to another object, even if that information is just that some event has occurred. They help to lower the code's coupling by providing a more detached communication mechanism that allows one object to send information to another, while having as little knowledge about the other object as possible. The less any type knows about the rest of the types in the code base, the less it will depend on those types. These behavior patterns also help to increase cohesion by providing straightforward and understandable ways to send the information.

This can often be the difference between doing something, such as calling your sister to ask your mom to ask your grandpa what he wants for his birthday and being able to ask your grandpa directly because you have a good communication channel open with him. In general, we will want to have the direct channel of communication open but sometimes it is actually better design to interact with fewer people, as long as we don't put too much burden on the other components. Behavioral patterns can help us with this.

The first behavioral pattern we will discuss is called the iterator pattern. We are starting with this one because we have actually already made use of this pattern in Chapter 6, Make Swift Work For You – Protocols and Generics. The idea of the iterator pattern is to provide a way to step through the contents of a container independent of the way the elements are represented inside the container.

As we saw, Swift provides us with the basics of this pattern with the GeneratorType and SequenceType protocols. It even implements those protocols for its array and dictionary containers. Even though we don't know how the elements are stored within an array or dictionary, we are still able to step through each value contained within them. Apple can easily change the way the elements are stored within them and it would not affect how we loop through the containers at all. This shows a great decoupling between our code and the container implementations.

If you remember, we were even able to create a generator for the infinite Fibonacci sequence:

struct FibonacciGenerator: GeneratorType {
    typealias Element = Int

    var values = (0, 1)

    mutating func next() -> Element? {
        self.values = (
            self.values.1,
            self.values.0 + self.values.1
        )
        return self.values.0
    }
}

The "container" doesn't even store any elements but we can still iterate through them as if it did.

The iterator pattern is a great introduction to how we make real world use of design patterns. Stepping through a list is such a common problem that Apple built the pattern directly into Swift.

The other behavioral pattern that we will discuss is called the observer pattern. The basic idea of this pattern is that you have one object that is designed to allow other objects to be notified when something occurs.

In Swift, the easiest way to achieve this is to provide a closure property on the object that you want to be observable and have that object call the closure whenever it wants to notify its observer. The property will be optional, so that any other object can set their closure on this property:

Here we have a class that represents an ATM that allows for withdrawing cash. It provides a closure property called onCashWithdrawn that is called every time cash is withdrawn. This type of closure property is usually called a callback. It is a good idea to make its purpose clear by its name. I personally choose to name all event-based callbacks by starting them with the word "on."

Now, any object can define its own closure on the callback and be notified whenever cash is withdrawn:

In this case, ATM is considered the observable object and the RecordKeeper is the observer. The ATM type is completely disconnected from whatever process might be keeping a record of its transactions. The record keeping mechanism can be changed without making any changes to the ATM and the ATM can be changed without any change to the RecordKeeper as long as the new ATM implementation still calls onCashWithDrawn whenever cash is withdrawn.

However, the RecordKeeper needs to be passed an ATM instance for this connection to be made. There can also only ever be one observer at a time. If we need to allow multiple observers, we can potentially provide an array of callbacks, but that can make removing observers more difficult. A solution that solves both of those problems is to implement the observer pattern using a notification center instead.

Iterator

The first

behavioral pattern we will discuss is called the iterator pattern. We are starting with this one because we have actually already made use of this pattern in Chapter 6, Make Swift Work For You – Protocols and Generics. The idea of the iterator pattern is to provide a way to step through the contents of a container independent of the way the elements are represented inside the container.

As we saw, Swift provides us with the basics of this pattern with the GeneratorType and SequenceType protocols. It even implements those protocols for its array and dictionary containers. Even though we don't know how the elements are stored within an array or dictionary, we are still able to step through each value contained within them. Apple can easily change the way the elements are stored within them and it would not affect how we loop through the containers at all. This shows a great decoupling between our code and the container implementations.

If you remember, we were even able to create a generator for the infinite Fibonacci sequence:

struct FibonacciGenerator: GeneratorType {
    typealias Element = Int

    var values = (0, 1)

    mutating func next() -> Element? {
        self.values = (
            self.values.1,
            self.values.0 + self.values.1
        )
        return self.values.0
    }
}

The "container" doesn't even store any elements but we can still iterate through them as if it did.

The iterator pattern is a great introduction to how we make real world use of design patterns. Stepping through a list is such a common problem that Apple built the pattern directly into Swift.

The other behavioral pattern that we will discuss is called the observer pattern. The basic idea of this pattern is that you have one object that is designed to allow other objects to be notified when something occurs.

In Swift, the easiest way to achieve this is to provide a closure property on the object that you want to be observable and have that object call the closure whenever it wants to notify its observer. The property will be optional, so that any other object can set their closure on this property:

Here we have a class that represents an ATM that allows for withdrawing cash. It provides a closure property called onCashWithdrawn that is called every time cash is withdrawn. This type of closure property is usually called a callback. It is a good idea to make its purpose clear by its name. I personally choose to name all event-based callbacks by starting them with the word "on."

Now, any object can define its own closure on the callback and be notified whenever cash is withdrawn:

In this case, ATM is considered the observable object and the RecordKeeper is the observer. The ATM type is completely disconnected from whatever process might be keeping a record of its transactions. The record keeping mechanism can be changed without making any changes to the ATM and the ATM can be changed without any change to the RecordKeeper as long as the new ATM implementation still calls onCashWithDrawn whenever cash is withdrawn.

However, the RecordKeeper needs to be passed an ATM instance for this connection to be made. There can also only ever be one observer at a time. If we need to allow multiple observers, we can potentially provide an array of callbacks, but that can make removing observers more difficult. A solution that solves both of those problems is to implement the observer pattern using a notification center instead.

Observer

The other

behavioral pattern that we will discuss is called the observer pattern. The basic idea of this pattern is that you have one object that is designed to allow other objects to be notified when something occurs.

In Swift, the easiest way to achieve this is to provide a closure property on the object that you want to be observable and have that object call the closure whenever it wants to notify its observer. The property will be optional, so that any other object can set their closure on this property:

Here we have a class that represents an ATM that allows for withdrawing cash. It provides a closure property called onCashWithdrawn that is called every time cash is withdrawn. This type of closure property is usually called a callback. It is a good idea to make its purpose clear by its name. I personally choose to name all event-based callbacks by starting them with the word "on."

Now, any object can define its own closure on the callback and be notified whenever cash is withdrawn:

In this case, ATM is considered the observable object and the RecordKeeper is the observer. The ATM type is completely disconnected from whatever process might be keeping a record of its transactions. The record keeping mechanism can be changed without making any changes to the ATM and the ATM can be changed without any change to the RecordKeeper as long as the new ATM implementation still calls onCashWithDrawn whenever cash is withdrawn.

However, the RecordKeeper needs to be passed an ATM instance for this connection to be made. There can also only ever be one observer at a time. If we need to allow multiple observers, we can potentially provide an array of callbacks, but that can make removing observers more difficult. A solution that solves both of those problems is to implement the observer pattern using a notification center instead.

Callback

In Swift, the

easiest way to achieve this is to provide a closure property on the object that you want to be observable and have that object call the closure whenever it wants to notify its observer. The property will be optional, so that any other object can set their closure on this property:

Here we have a class that represents an ATM that allows for withdrawing cash. It provides a closure property called onCashWithdrawn that is called every time cash is withdrawn. This type of closure property is usually called a callback. It is a good idea to make its purpose clear by its name. I personally choose to name all event-based callbacks by starting them with the word "on."

Now, any object can define its own closure on the callback and be notified whenever cash is withdrawn:

In this case, ATM is considered the observable object and the RecordKeeper is the observer. The ATM type is completely disconnected from whatever process might be keeping a record of its transactions. The record keeping mechanism can be changed without making any changes to the ATM and the ATM can be changed without any change to the RecordKeeper as long as the new ATM implementation still calls onCashWithDrawn whenever cash is withdrawn.

However, the RecordKeeper needs to be passed an ATM instance for this connection to be made. There can also only ever be one observer at a time. If we need to allow multiple observers, we can potentially provide an array of callbacks, but that can make removing observers more difficult. A solution that solves both of those problems is to implement the observer pattern using a notification center instead.

Notification center

A

Structural patterns are patterns that describe how objects should relate to each other so that they can work together to achieve a common goal. They help us lower our coupling by suggesting an easy and clear way to break down a problem into related parts and they help raise our cohesion by giving us a predefined way that those components will fit together.

This is like a sports team defining specific roles for each person on the field so that they can play together better as a whole.

The first structural pattern we are going to look at is called the composite pattern. The concept of this pattern is that you have a single object that can be broken down into a collection of objects just like itself. This is like the organization of many large companies. They will have teams that are made up of smaller teams, which are then made up of even smaller teams. Each sub-team is responsible for a small part and they come together to be responsible for a larger part of the company.

A computer ultimately represents what is on the screen with a grid of pixel data. However, it does not make sense for every program to be concerned with each individual pixel. Instead, most programmers use frameworks, often provided by the operating system, to manipulate what is on the screen at a much higher level. A graphical program is usually given one or more windows to draw within and instead of drawing pixels within a window; a program will usually set up a series of "views". A view will have lots of different properties but they will most importantly have a position, size, and background color.

We can potentially build up an entire window with just a big list of views but programmers have devised a way of using the composite pattern to make the whole process much more intuitive. A view can actually contain other views, which are generally referred to as subviews. In this sense, you can look at any view like a tree of subviews. If you look at the very root of the tree, you will see a complete image of what will be displayed on the window. However, you can look at any of the tree branches or leaves and see a smaller part of that view. This is the same as looking at a large team as a whole versus looking at a small team within that larger team. In all of this, there is no difference between a view at the root of the tree and a view at the leaf of the tree, except the root has more sub-views.

Let's look at our own implementation of a View class:

This is a pretty simple class, but by adding the subviews property, which is an array of additional views, we are using the composite pattern to make this a very powerful class. You can imagine a virtually infinite hierarchy of views that are all contained within a single parent view. That single view could be passed to some other class that could draw the entire hierarchy of views.

As an example, let's set up a view that has red in the left-half, green in the upper-right half, and blue in the lower-right half:

Hierarchies

To produce this with our class, we could write a code similar to:

In this implementation, we actually have a red left half as defined by leftView and a blue right half as defined by rightView. The reason the upper-right half is green instead of blue is that we added upperRightView as a subview to rightView and only made it half the height. This means that our view hierarchy looks similar to the following image:

Hierarchies

It is important to note that the position of upperRightView is left at 0, 0. That is because the positioning of all sub-views will always be relative to their immediate parent view. This allows us to pull any view out of the hierarchy without affecting any of its sub-views; drawing rightView within rootView will look exactly the same as if it were drawn on its own.

You could also set up separate objects to manage the contents of different subsections of the main view. For example, to create a program like Xcode, we might have one object that manages the contents of the file list on the left and a different object that manages the display of the selected file. Clearly, Xcode is much more complex than that, but it gives us an idea of how we can build incredibly powerful and complex software with relatively simple concepts.

You may, however, have noticed a potential problem with our view class. What would happen if we added a view to its own subview hierarchy somewhere. That is most likely going to cause an infinite loop when another part of our code goes to draw the view. As another challenge to you, try to update our View class to prevent this from happening. I suggest you start by making subviews private and providing methods for adding and removing subviews. You will probably also want to add an optional superview property that will reference the parent view.

As you can see, the composite pattern is ideal for any situation where an object can be broken down into pieces that are just like it. This is great for something seemingly infinite like a hierarchy of views, but it is also a great alternative to subclassing. Subclassing is actually the tightest form of coupling. A subclass is extremely dependent on its superclass. Any change to a superclass is almost certainly going to affect all of its subclasses. We can often use the composite pattern as a less coupled alternative to subclassing.

As an example, let's explore the concept of representing a sentence. One way to look at the problem is to consider the sentence a special kind of string. Any kind of specialization like this will usually lead us to create a subclass; after all, a subclass is a specialization of its superclass. So we could create a Sentence subclass of String. This will be great because we can build strings using our sentence class and then pass them to methods that are expecting a normal string.

However, there is an important obstacle to this method: we don't have control of the String code and even worse we can't even look at the code so we don't even know how the characters are stored. This means that the code can be changed underneath us with an update from Apple without our knowledge. Even with our knowledge, this could cause a maintenance headache.

A better solution would be to use the composite pattern and implement a Sentence type that contains strings:

Here, we were able to give more meaningful names to the parts of the sentence with various words and we set up a Type enumeration that allows us to use different end punctuations. As a convenience, we can even add a string calculated property so that we can use the sentence as a normal string:

This is a much better alternative to subclassing in this scenario.

One of the most commonly used design patterns in Apple's frameworks is called the delegate pattern. The idea behind it is that you set up an object to let another object handle some of its responsibilities. In other words, one object will delegate some of its responsibilities to another object. This is like a manager hiring employees to do a job that the manager cannot or does not want to do themselves.

As a more technical example, on iOS, Apple provides a user interface class called UITableView. As the name suggest, this class provides us with an easy way to draw a list of elements. On its own, a UITableView isn't enough to make an interface. It needs data to display and it needs to be able to handle all kinds of user interactions, such as tapping, reordering, deleting, and so on.

One instinct is to create your own subclass of UITableView, maybe something like PeopleTableView. This is an OK option until you remember how we discussed that subclassing is actually the strongest type of coupling between two objects. In order to properly subclass a UITableView, you would have to be pretty intimately aware of how the superclass works. This is especially difficult when you are not even allowed to see the code of the superclass.

Another option is to set data on the table view and use the observer pattern to handle user interactions. This is better than the subclassing option, but most data you will want to display is not static and therefore it would be cumbersome to make updates to the table view. It will also still be hard to implement an object that can be reused easily for other ways of displaying a list of information.

So instead, what Apple did is, they created two different properties on UITableView: delegate and dataSource. These properties are there so that we can assign our own objects to handle various responsibilities for the table. The data source is primarily responsible for providing the information to be shown in the table and the delegate's responsibility is to handle user interaction. Of course, if these objects could be of any type, the table view would not really be able to interact with them. Also, if these objects were of a specific type, we would still run into the same subclassing problem. Instead, they are defined to implement the UITableViewDelegate and UITableViewDataSource protocols respectively.

These protocols define only the methods necessary to allow the table view to properly function. This means that the delegate and dataSource properties can be any type as long as they implement the necessary methods. For example, one of the critical methods the data source must implement is tableView:numberOfRowsInSection:. This method provides the table view and an integer referring to the section that it wants to know about. It requires that an integer be returned for the number of rows in the referenced section. This is only one of multiple methods that data source must implement, but it gives you an idea of how the table view no longer has to figure out what data it contains. It simply asks the data source to figure it out.

This provides a very loosely coupled way to implement a specific table view and this same pattern is reused all over the programming world. You would be amazed at what Apple has been able to do with its table view, with very little to no pain inflicted on third party developers. The table view is incredibly optimized to handle thousands upon thousands of rows if you really wanted it to. The table has also changed a lot since the first developer kit for iOS, but these protocols have very rarely been changed except to add additional features.

Model view controller is one of the highest levels and most abstract design patterns. Variations of it are pervasive across a huge percentage of software, especially Apple's frameworks. It really can be considered the foundational pattern for how all of Apple's code is designed and therefore how most third party developers design their own code. The core concept of model view controller is that you split all of your types into three categories, often referred to as layers: model, view, and controller.

The model layer is for all of the types that represent and manipulate data. This layer is the real foundation of what your software can do for its user, so it is also often referred to as the business logic. For example, the model layer from an address book app would have types representing contacts, groups, and so on. It would also contain logic to create, delete, modify, and store those types.

The view layer is for all types involved in the display and interaction of your software. It consists of types like tables, text view, and buttons. Essentially, this layer is responsible for displaying information to the user and providing the affordances for how a user can interact with your application. The view in an address book app would consist of the displayed list of contacts, groups, and contact information.

The final layer, controller, is mostly just the glue code between the model and view layers. It will instruct the view of what to display based on the data in the model layer and it will trigger the right business logic depending on the interactions coming from the view layer. In our address book example, the controller layer would connect something such as a contact add button in the view, to the logic defined in the model for creating a new contact. It will also connect things like the on screen table view to the list of contacts in the model.

In the ideal implementation of model view controller, no model type should ever have any knowledge of the existence of a view type and no view type should know about a model type. Often, a model view controller is visualized sort of like a cake:

Model view controller

The user sees and interacts with the top of the cake and each layer only communicates with its adjacent layers. This means that all communication between the view and the model layers should go through the controller layer. At the same time, the controller layer should be pretty lightweight, because the model layer is doing the heavy lifting on the logic side of the application and the view layer is doing the heavy lifting on drawing to the screen and accepting user input.

One of the main benefits of this design pattern is that it provides a logical and consistent way to break down many pieces of software. This greatly increases your ability to share your code with other developers and understand their code. It gives everyone a frame of reference for when they try to understand another large code base that they haven't seen before. The naming of classes also gives strong clues to developers about what role a type will play in the overall system. Virtually every view class in iOS has the word "view" in it: UITableView, UIView, UICollectionViewCell, etc. Also, most of the controller layer classes that Apple provides have the word controller in them: UIViewController, UITableViewController, MFMailComposeViewController, etc. The model layer is mostly left to third party developers, other than the basic data types, since Apple isn't going to be able to help much with the business logic of your software. However, even among third party developers, these classes are often nouns named after the data they are representing or manipulating: Person, AddressBook, Publisher, and so on.

Another huge benefit of model view controller is that most components will be very reusable. You should be able to easily reuse views with different types of data like you can use a table view to display virtually any kind of data without changing the table view type and you should be able to display something like an address book in lots of different ways without changing the address book type.

As useful as this pattern is, it is also extremely hard to stick to. You will probably spend your entire development career evolving your sense for how to effectively breakdown your problems into these layers. It is often helpful to create explicit folders for each layer, forcing yourself to put every type into only one of the categories. You will also probably find yourself creating a bloated controller layer, especially in iOS, because it is often convenient to stick business logic there. More than any other design pattern, model view controller is probably the one that can be most described as something you strive for but rarely ever perfectly achieve.

Composite

The

first structural pattern we are going to look at is called the composite pattern. The concept of this pattern is that you have a single object that can be broken down into a collection of objects just like itself. This is like the organization of many large companies. They will have teams that are made up of smaller teams, which are then made up of even smaller teams. Each sub-team is responsible for a small part and they come together to be responsible for a larger part of the company.

A computer ultimately represents what is on the screen with a grid of pixel data. However, it does not make sense for every program to be concerned with each individual pixel. Instead, most programmers use frameworks, often provided by the operating system, to manipulate what is on the screen at a much higher level. A graphical program is usually given one or more windows to draw within and instead of drawing pixels within a window; a program will usually set up a series of "views". A view will have lots of different properties but they will most importantly have a position, size, and background color.

We can potentially build up an entire window with just a big list of views but programmers have devised a way of using the composite pattern to make the whole process much more intuitive. A view can actually contain other views, which are generally referred to as subviews. In this sense, you can look at any view like a tree of subviews. If you look at the very root of the tree, you will see a complete image of what will be displayed on the window. However, you can look at any of the tree branches or leaves and see a smaller part of that view. This is the same as looking at a large team as a whole versus looking at a small team within that larger team. In all of this, there is no difference between a view at the root of the tree and a view at the leaf of the tree, except the root has more sub-views.

Let's look at our own implementation of a View class:

This is a pretty simple class, but by adding the subviews property, which is an array of additional views, we are using the composite pattern to make this a very powerful class. You can imagine a virtually infinite hierarchy of views that are all contained within a single parent view. That single view could be passed to some other class that could draw the entire hierarchy of views.

As an example, let's set up a view that has red in the left-half, green in the upper-right half, and blue in the lower-right half:

Hierarchies

To produce this with our class, we could write a code similar to:

In this implementation, we actually have a red left half as defined by leftView and a blue right half as defined by rightView. The reason the upper-right half is green instead of blue is that we added upperRightView as a subview to rightView and only made it half the height. This means that our view hierarchy looks similar to the following image:

Hierarchies

It is important to note that the position of upperRightView is left at 0, 0. That is because the positioning of all sub-views will always be relative to their immediate parent view. This allows us to pull any view out of the hierarchy without affecting any of its sub-views; drawing rightView within rootView will look exactly the same as if it were drawn on its own.

You could also set up separate objects to manage the contents of different subsections of the main view. For example, to create a program like Xcode, we might have one object that manages the contents of the file list on the left and a different object that manages the display of the selected file. Clearly, Xcode is much more complex than that, but it gives us an idea of how we can build incredibly powerful and complex software with relatively simple concepts.

You may, however, have noticed a potential problem with our view class. What would happen if we added a view to its own subview hierarchy somewhere. That is most likely going to cause an infinite loop when another part of our code goes to draw the view. As another challenge to you, try to update our View class to prevent this from happening. I suggest you start by making subviews private and providing methods for adding and removing subviews. You will probably also want to add an optional superview property that will reference the parent view.

As you can see, the composite pattern is ideal for any situation where an object can be broken down into pieces that are just like it. This is great for something seemingly infinite like a hierarchy of views, but it is also a great alternative to subclassing. Subclassing is actually the tightest form of coupling. A subclass is extremely dependent on its superclass. Any change to a superclass is almost certainly going to affect all of its subclasses. We can often use the composite pattern as a less coupled alternative to subclassing.

As an example, let's explore the concept of representing a sentence. One way to look at the problem is to consider the sentence a special kind of string. Any kind of specialization like this will usually lead us to create a subclass; after all, a subclass is a specialization of its superclass. So we could create a Sentence subclass of String. This will be great because we can build strings using our sentence class and then pass them to methods that are expecting a normal string.

However, there is an important obstacle to this method: we don't have control of the String code and even worse we can't even look at the code so we don't even know how the characters are stored. This means that the code can be changed underneath us with an update from Apple without our knowledge. Even with our knowledge, this could cause a maintenance headache.

A better solution would be to use the composite pattern and implement a Sentence type that contains strings:

Here, we were able to give more meaningful names to the parts of the sentence with various words and we set up a Type enumeration that allows us to use different end punctuations. As a convenience, we can even add a string calculated property so that we can use the sentence as a normal string:

This is a much better alternative to subclassing in this scenario.

One of the most commonly used design patterns in Apple's frameworks is called the delegate pattern. The idea behind it is that you set up an object to let another object handle some of its responsibilities. In other words, one object will delegate some of its responsibilities to another object. This is like a manager hiring employees to do a job that the manager cannot or does not want to do themselves.

As a more technical example, on iOS, Apple provides a user interface class called UITableView. As the name suggest, this class provides us with an easy way to draw a list of elements. On its own, a UITableView isn't enough to make an interface. It needs data to display and it needs to be able to handle all kinds of user interactions, such as tapping, reordering, deleting, and so on.

One instinct is to create your own subclass of UITableView, maybe something like PeopleTableView. This is an OK option until you remember how we discussed that subclassing is actually the strongest type of coupling between two objects. In order to properly subclass a UITableView, you would have to be pretty intimately aware of how the superclass works. This is especially difficult when you are not even allowed to see the code of the superclass.

Another option is to set data on the table view and use the observer pattern to handle user interactions. This is better than the subclassing option, but most data you will want to display is not static and therefore it would be cumbersome to make updates to the table view. It will also still be hard to implement an object that can be reused easily for other ways of displaying a list of information.

So instead, what Apple did is, they created two different properties on UITableView: delegate and dataSource. These properties are there so that we can assign our own objects to handle various responsibilities for the table. The data source is primarily responsible for providing the information to be shown in the table and the delegate's responsibility is to handle user interaction. Of course, if these objects could be of any type, the table view would not really be able to interact with them. Also, if these objects were of a specific type, we would still run into the same subclassing problem. Instead, they are defined to implement the UITableViewDelegate and UITableViewDataSource protocols respectively.

These protocols define only the methods necessary to allow the table view to properly function. This means that the delegate and dataSource properties can be any type as long as they implement the necessary methods. For example, one of the critical methods the data source must implement is tableView:numberOfRowsInSection:. This method provides the table view and an integer referring to the section that it wants to know about. It requires that an integer be returned for the number of rows in the referenced section. This is only one of multiple methods that data source must implement, but it gives you an idea of how the table view no longer has to figure out what data it contains. It simply asks the data source to figure it out.

This provides a very loosely coupled way to implement a specific table view and this same pattern is reused all over the programming world. You would be amazed at what Apple has been able to do with its table view, with very little to no pain inflicted on third party developers. The table view is incredibly optimized to handle thousands upon thousands of rows if you really wanted it to. The table has also changed a lot since the first developer kit for iOS, but these protocols have very rarely been changed except to add additional features.

Model view controller is one of the highest levels and most abstract design patterns. Variations of it are pervasive across a huge percentage of software, especially Apple's frameworks. It really can be considered the foundational pattern for how all of Apple's code is designed and therefore how most third party developers design their own code. The core concept of model view controller is that you split all of your types into three categories, often referred to as layers: model, view, and controller.

The model layer is for all of the types that represent and manipulate data. This layer is the real foundation of what your software can do for its user, so it is also often referred to as the business logic. For example, the model layer from an address book app would have types representing contacts, groups, and so on. It would also contain logic to create, delete, modify, and store those types.

The view layer is for all types involved in the display and interaction of your software. It consists of types like tables, text view, and buttons. Essentially, this layer is responsible for displaying information to the user and providing the affordances for how a user can interact with your application. The view in an address book app would consist of the displayed list of contacts, groups, and contact information.

The final layer, controller, is mostly just the glue code between the model and view layers. It will instruct the view of what to display based on the data in the model layer and it will trigger the right business logic depending on the interactions coming from the view layer. In our address book example, the controller layer would connect something such as a contact add button in the view, to the logic defined in the model for creating a new contact. It will also connect things like the on screen table view to the list of contacts in the model.

In the ideal implementation of model view controller, no model type should ever have any knowledge of the existence of a view type and no view type should know about a model type. Often, a model view controller is visualized sort of like a cake:

Model view controller

The user sees and interacts with the top of the cake and each layer only communicates with its adjacent layers. This means that all communication between the view and the model layers should go through the controller layer. At the same time, the controller layer should be pretty lightweight, because the model layer is doing the heavy lifting on the logic side of the application and the view layer is doing the heavy lifting on drawing to the screen and accepting user input.

One of the main benefits of this design pattern is that it provides a logical and consistent way to break down many pieces of software. This greatly increases your ability to share your code with other developers and understand their code. It gives everyone a frame of reference for when they try to understand another large code base that they haven't seen before. The naming of classes also gives strong clues to developers about what role a type will play in the overall system. Virtually every view class in iOS has the word "view" in it: UITableView, UIView, UICollectionViewCell, etc. Also, most of the controller layer classes that Apple provides have the word controller in them: UIViewController, UITableViewController, MFMailComposeViewController, etc. The model layer is mostly left to third party developers, other than the basic data types, since Apple isn't going to be able to help much with the business logic of your software. However, even among third party developers, these classes are often nouns named after the data they are representing or manipulating: Person, AddressBook, Publisher, and so on.

Another huge benefit of model view controller is that most components will be very reusable. You should be able to easily reuse views with different types of data like you can use a table view to display virtually any kind of data without changing the table view type and you should be able to display something like an address book in lots of different ways without changing the address book type.

As useful as this pattern is, it is also extremely hard to stick to. You will probably spend your entire development career evolving your sense for how to effectively breakdown your problems into these layers. It is often helpful to create explicit folders for each layer, forcing yourself to put every type into only one of the categories. You will also probably find yourself creating a bloated controller layer, especially in iOS, because it is often convenient to stick business logic there. More than any other design pattern, model view controller is probably the one that can be most described as something you strive for but rarely ever perfectly achieve.

Hierarchies

A

computer ultimately represents what is on the screen with a grid of pixel data. However, it does not make sense for every program to be concerned with each individual pixel. Instead, most programmers use frameworks, often provided by the operating system, to manipulate what is on the screen at a much higher level. A graphical program is usually given one or more windows to draw within and instead of drawing pixels within a window; a program will usually set up a series of "views". A view will have lots of different properties but they will most importantly have a position, size, and background color.

We can potentially build up an entire window with just a big list of views but programmers have devised a way of using the composite pattern to make the whole process much more intuitive. A view can actually contain other views, which are generally referred to as subviews. In this sense, you can look at any view like a tree of subviews. If you look at the very root of the tree, you will see a complete image of what will be displayed on the window. However, you can look at any of the tree branches or leaves and see a smaller part of that view. This is the same as looking at a large team as a whole versus looking at a small team within that larger team. In all of this, there is no difference between a view at the root of the tree and a view at the leaf of the tree, except the root has more sub-views.

Let's look at our own implementation of a View class:

This is a pretty simple class, but by adding the subviews property, which is an array of additional views, we are using the composite pattern to make this a very powerful class. You can imagine a virtually infinite hierarchy of views that are all contained within a single parent view. That single view could be passed to some other class that could draw the entire hierarchy of views.

As an example, let's set up a view that has red in the left-half, green in the upper-right half, and blue in the lower-right half:

Hierarchies

To produce this with our class, we could write a code similar to:

In this implementation, we actually have a red left half as defined by leftView and a blue right half as defined by rightView. The reason the upper-right half is green instead of blue is that we added upperRightView as a subview to rightView and only made it half the height. This means that our view hierarchy looks similar to the following image:

Hierarchies

It is important to note that the position of upperRightView is left at 0, 0. That is because the positioning of all sub-views will always be relative to their immediate parent view. This allows us to pull any view out of the hierarchy without affecting any of its sub-views; drawing rightView within rootView will look exactly the same as if it were drawn on its own.

You could also set up separate objects to manage the contents of different subsections of the main view. For example, to create a program like Xcode, we might have one object that manages the contents of the file list on the left and a different object that manages the display of the selected file. Clearly, Xcode is much more complex than that, but it gives us an idea of how we can build incredibly powerful and complex software with relatively simple concepts.

You may, however, have noticed a potential problem with our view class. What would happen if we added a view to its own subview hierarchy somewhere. That is most likely going to cause an infinite loop when another part of our code goes to draw the view. As another challenge to you, try to update our View class to prevent this from happening. I suggest you start by making subviews private and providing methods for adding and removing subviews. You will probably also want to add an optional superview property that will reference the parent view.

As you can see, the composite pattern is ideal for any situation where an object can be broken down into pieces that are just like it. This is great for something seemingly infinite like a hierarchy of views, but it is also a great alternative to subclassing. Subclassing is actually the tightest form of coupling. A subclass is extremely dependent on its superclass. Any change to a superclass is almost certainly going to affect all of its subclasses. We can often use the composite pattern as a less coupled alternative to subclassing.

As an example, let's explore the concept of representing a sentence. One way to look at the problem is to consider the sentence a special kind of string. Any kind of specialization like this will usually lead us to create a subclass; after all, a subclass is a specialization of its superclass. So we could create a Sentence subclass of String. This will be great because we can build strings using our sentence class and then pass them to methods that are expecting a normal string.

However, there is an important obstacle to this method: we don't have control of the String code and even worse we can't even look at the code so we don't even know how the characters are stored. This means that the code can be changed underneath us with an update from Apple without our knowledge. Even with our knowledge, this could cause a maintenance headache.

A better solution would be to use the composite pattern and implement a Sentence type that contains strings:

Here, we were able to give more meaningful names to the parts of the sentence with various words and we set up a Type enumeration that allows us to use different end punctuations. As a convenience, we can even add a string calculated property so that we can use the sentence as a normal string:

This is a much better alternative to subclassing in this scenario.

One of the most commonly used design patterns in Apple's frameworks is called the delegate pattern. The idea behind it is that you set up an object to let another object handle some of its responsibilities. In other words, one object will delegate some of its responsibilities to another object. This is like a manager hiring employees to do a job that the manager cannot or does not want to do themselves.

As a more technical example, on iOS, Apple provides a user interface class called UITableView. As the name suggest, this class provides us with an easy way to draw a list of elements. On its own, a UITableView isn't enough to make an interface. It needs data to display and it needs to be able to handle all kinds of user interactions, such as tapping, reordering, deleting, and so on.

One instinct is to create your own subclass of UITableView, maybe something like PeopleTableView. This is an OK option until you remember how we discussed that subclassing is actually the strongest type of coupling between two objects. In order to properly subclass a UITableView, you would have to be pretty intimately aware of how the superclass works. This is especially difficult when you are not even allowed to see the code of the superclass.

Another option is to set data on the table view and use the observer pattern to handle user interactions. This is better than the subclassing option, but most data you will want to display is not static and therefore it would be cumbersome to make updates to the table view. It will also still be hard to implement an object that can be reused easily for other ways of displaying a list of information.

So instead, what Apple did is, they created two different properties on UITableView: delegate and dataSource. These properties are there so that we can assign our own objects to handle various responsibilities for the table. The data source is primarily responsible for providing the information to be shown in the table and the delegate's responsibility is to handle user interaction. Of course, if these objects could be of any type, the table view would not really be able to interact with them. Also, if these objects were of a specific type, we would still run into the same subclassing problem. Instead, they are defined to implement the UITableViewDelegate and UITableViewDataSource protocols respectively.

These protocols define only the methods necessary to allow the table view to properly function. This means that the delegate and dataSource properties can be any type as long as they implement the necessary methods. For example, one of the critical methods the data source must implement is tableView:numberOfRowsInSection:. This method provides the table view and an integer referring to the section that it wants to know about. It requires that an integer be returned for the number of rows in the referenced section. This is only one of multiple methods that data source must implement, but it gives you an idea of how the table view no longer has to figure out what data it contains. It simply asks the data source to figure it out.

This provides a very loosely coupled way to implement a specific table view and this same pattern is reused all over the programming world. You would be amazed at what Apple has been able to do with its table view, with very little to no pain inflicted on third party developers. The table view is incredibly optimized to handle thousands upon thousands of rows if you really wanted it to. The table has also changed a lot since the first developer kit for iOS, but these protocols have very rarely been changed except to add additional features.

Model view controller is one of the highest levels and most abstract design patterns. Variations of it are pervasive across a huge percentage of software, especially Apple's frameworks. It really can be considered the foundational pattern for how all of Apple's code is designed and therefore how most third party developers design their own code. The core concept of model view controller is that you split all of your types into three categories, often referred to as layers: model, view, and controller.

The model layer is for all of the types that represent and manipulate data. This layer is the real foundation of what your software can do for its user, so it is also often referred to as the business logic. For example, the model layer from an address book app would have types representing contacts, groups, and so on. It would also contain logic to create, delete, modify, and store those types.

The view layer is for all types involved in the display and interaction of your software. It consists of types like tables, text view, and buttons. Essentially, this layer is responsible for displaying information to the user and providing the affordances for how a user can interact with your application. The view in an address book app would consist of the displayed list of contacts, groups, and contact information.

The final layer, controller, is mostly just the glue code between the model and view layers. It will instruct the view of what to display based on the data in the model layer and it will trigger the right business logic depending on the interactions coming from the view layer. In our address book example, the controller layer would connect something such as a contact add button in the view, to the logic defined in the model for creating a new contact. It will also connect things like the on screen table view to the list of contacts in the model.

In the ideal implementation of model view controller, no model type should ever have any knowledge of the existence of a view type and no view type should know about a model type. Often, a model view controller is visualized sort of like a cake:

Model view controller

The user sees and interacts with the top of the cake and each layer only communicates with its adjacent layers. This means that all communication between the view and the model layers should go through the controller layer. At the same time, the controller layer should be pretty lightweight, because the model layer is doing the heavy lifting on the logic side of the application and the view layer is doing the heavy lifting on drawing to the screen and accepting user input.

One of the main benefits of this design pattern is that it provides a logical and consistent way to break down many pieces of software. This greatly increases your ability to share your code with other developers and understand their code. It gives everyone a frame of reference for when they try to understand another large code base that they haven't seen before. The naming of classes also gives strong clues to developers about what role a type will play in the overall system. Virtually every view class in iOS has the word "view" in it: UITableView, UIView, UICollectionViewCell, etc. Also, most of the controller layer classes that Apple provides have the word controller in them: UIViewController, UITableViewController, MFMailComposeViewController, etc. The model layer is mostly left to third party developers, other than the basic data types, since Apple isn't going to be able to help much with the business logic of your software. However, even among third party developers, these classes are often nouns named after the data they are representing or manipulating: Person, AddressBook, Publisher, and so on.

Another huge benefit of model view controller is that most components will be very reusable. You should be able to easily reuse views with different types of data like you can use a table view to display virtually any kind of data without changing the table view type and you should be able to display something like an address book in lots of different ways without changing the address book type.

As useful as this pattern is, it is also extremely hard to stick to. You will probably spend your entire development career evolving your sense for how to effectively breakdown your problems into these layers. It is often helpful to create explicit folders for each layer, forcing yourself to put every type into only one of the categories. You will also probably find yourself creating a bloated controller layer, especially in iOS, because it is often convenient to stick business logic there. More than any other design pattern, model view controller is probably the one that can be most described as something you strive for but rarely ever perfectly achieve.

Alternative to subclassing

As you

can see, the composite pattern is ideal for any situation where an object can be broken down into pieces that are just like it. This is great for something seemingly infinite like a hierarchy of views, but it is also a great alternative to subclassing. Subclassing is actually the tightest form of coupling. A subclass is extremely dependent on its superclass. Any change to a superclass is almost certainly going to affect all of its subclasses. We can often use the composite pattern as a less coupled alternative to subclassing.

As an example, let's explore the concept of representing a sentence. One way to look at the problem is to consider the sentence a special kind of string. Any kind of specialization like this will usually lead us to create a subclass; after all, a subclass is a specialization of its superclass. So we could create a Sentence subclass of String. This will be great because we can build strings using our sentence class and then pass them to methods that are expecting a normal string.

However, there is an important obstacle to this method: we don't have control of the String code and even worse we can't even look at the code so we don't even know how the characters are stored. This means that the code can be changed underneath us with an update from Apple without our knowledge. Even with our knowledge, this could cause a maintenance headache.

A better solution would be to use the composite pattern and implement a Sentence type that contains strings:

Here, we were able to give more meaningful names to the parts of the sentence with various words and we set up a Type enumeration that allows us to use different end punctuations. As a convenience, we can even add a string calculated property so that we can use the sentence as a normal string:

This is a much better alternative to subclassing in this scenario.

One of the most commonly used design patterns in Apple's frameworks is called the delegate pattern. The idea behind it is that you set up an object to let another object handle some of its responsibilities. In other words, one object will delegate some of its responsibilities to another object. This is like a manager hiring employees to do a job that the manager cannot or does not want to do themselves.

As a more technical example, on iOS, Apple provides a user interface class called UITableView. As the name suggest, this class provides us with an easy way to draw a list of elements. On its own, a UITableView isn't enough to make an interface. It needs data to display and it needs to be able to handle all kinds of user interactions, such as tapping, reordering, deleting, and so on.

One instinct is to create your own subclass of UITableView, maybe something like PeopleTableView. This is an OK option until you remember how we discussed that subclassing is actually the strongest type of coupling between two objects. In order to properly subclass a UITableView, you would have to be pretty intimately aware of how the superclass works. This is especially difficult when you are not even allowed to see the code of the superclass.

Another option is to set data on the table view and use the observer pattern to handle user interactions. This is better than the subclassing option, but most data you will want to display is not static and therefore it would be cumbersome to make updates to the table view. It will also still be hard to implement an object that can be reused easily for other ways of displaying a list of information.

So instead, what Apple did is, they created two different properties on UITableView: delegate and dataSource. These properties are there so that we can assign our own objects to handle various responsibilities for the table. The data source is primarily responsible for providing the information to be shown in the table and the delegate's responsibility is to handle user interaction. Of course, if these objects could be of any type, the table view would not really be able to interact with them. Also, if these objects were of a specific type, we would still run into the same subclassing problem. Instead, they are defined to implement the UITableViewDelegate and UITableViewDataSource protocols respectively.

These protocols define only the methods necessary to allow the table view to properly function. This means that the delegate and dataSource properties can be any type as long as they implement the necessary methods. For example, one of the critical methods the data source must implement is tableView:numberOfRowsInSection:. This method provides the table view and an integer referring to the section that it wants to know about. It requires that an integer be returned for the number of rows in the referenced section. This is only one of multiple methods that data source must implement, but it gives you an idea of how the table view no longer has to figure out what data it contains. It simply asks the data source to figure it out.

This provides a very loosely coupled way to implement a specific table view and this same pattern is reused all over the programming world. You would be amazed at what Apple has been able to do with its table view, with very little to no pain inflicted on third party developers. The table view is incredibly optimized to handle thousands upon thousands of rows if you really wanted it to. The table has also changed a lot since the first developer kit for iOS, but these protocols have very rarely been changed except to add additional features.

Model view controller is one of the highest levels and most abstract design patterns. Variations of it are pervasive across a huge percentage of software, especially Apple's frameworks. It really can be considered the foundational pattern for how all of Apple's code is designed and therefore how most third party developers design their own code. The core concept of model view controller is that you split all of your types into three categories, often referred to as layers: model, view, and controller.

The model layer is for all of the types that represent and manipulate data. This layer is the real foundation of what your software can do for its user, so it is also often referred to as the business logic. For example, the model layer from an address book app would have types representing contacts, groups, and so on. It would also contain logic to create, delete, modify, and store those types.

The view layer is for all types involved in the display and interaction of your software. It consists of types like tables, text view, and buttons. Essentially, this layer is responsible for displaying information to the user and providing the affordances for how a user can interact with your application. The view in an address book app would consist of the displayed list of contacts, groups, and contact information.

The final layer, controller, is mostly just the glue code between the model and view layers. It will instruct the view of what to display based on the data in the model layer and it will trigger the right business logic depending on the interactions coming from the view layer. In our address book example, the controller layer would connect something such as a contact add button in the view, to the logic defined in the model for creating a new contact. It will also connect things like the on screen table view to the list of contacts in the model.

In the ideal implementation of model view controller, no model type should ever have any knowledge of the existence of a view type and no view type should know about a model type. Often, a model view controller is visualized sort of like a cake:

Model view controller

The user sees and interacts with the top of the cake and each layer only communicates with its adjacent layers. This means that all communication between the view and the model layers should go through the controller layer. At the same time, the controller layer should be pretty lightweight, because the model layer is doing the heavy lifting on the logic side of the application and the view layer is doing the heavy lifting on drawing to the screen and accepting user input.

One of the main benefits of this design pattern is that it provides a logical and consistent way to break down many pieces of software. This greatly increases your ability to share your code with other developers and understand their code. It gives everyone a frame of reference for when they try to understand another large code base that they haven't seen before. The naming of classes also gives strong clues to developers about what role a type will play in the overall system. Virtually every view class in iOS has the word "view" in it: UITableView, UIView, UICollectionViewCell, etc. Also, most of the controller layer classes that Apple provides have the word controller in them: UIViewController, UITableViewController, MFMailComposeViewController, etc. The model layer is mostly left to third party developers, other than the basic data types, since Apple isn't going to be able to help much with the business logic of your software. However, even among third party developers, these classes are often nouns named after the data they are representing or manipulating: Person, AddressBook, Publisher, and so on.

Another huge benefit of model view controller is that most components will be very reusable. You should be able to easily reuse views with different types of data like you can use a table view to display virtually any kind of data without changing the table view type and you should be able to display something like an address book in lots of different ways without changing the address book type.

As useful as this pattern is, it is also extremely hard to stick to. You will probably spend your entire development career evolving your sense for how to effectively breakdown your problems into these layers. It is often helpful to create explicit folders for each layer, forcing yourself to put every type into only one of the categories. You will also probably find yourself creating a bloated controller layer, especially in iOS, because it is often convenient to stick business logic there. More than any other design pattern, model view controller is probably the one that can be most described as something you strive for but rarely ever perfectly achieve.

Delegate

One of the most

commonly used design patterns in Apple's frameworks is called the delegate pattern. The idea behind it is that you set up an object to let another object handle some of its responsibilities. In other words, one object will delegate some of its responsibilities to another object. This is like a manager hiring employees to do a job that the manager cannot or does not want to do themselves.

As a more technical example, on iOS, Apple provides a user interface class called UITableView. As the name suggest, this class provides us with an easy way to draw a list of elements. On its own, a UITableView isn't enough to make an interface. It needs data to display and it needs to be able to handle all kinds of user interactions, such as tapping, reordering, deleting, and so on.

One instinct is to create your own subclass of UITableView, maybe something like PeopleTableView. This is an OK option until you remember how we discussed that subclassing is actually the strongest type of coupling between two objects. In order to properly subclass a UITableView, you would have to be pretty intimately aware of how the superclass works. This is especially difficult when you are not even allowed to see the code of the superclass.

Another option is to set data on the table view and use the observer pattern to handle user interactions. This is better than the subclassing option, but most data you will want to display is not static and therefore it would be cumbersome to make updates to the table view. It will also still be hard to implement an object that can be reused easily for other ways of displaying a list of information.

So instead, what Apple did is, they created two different properties on UITableView: delegate and dataSource. These properties are there so that we can assign our own objects to handle various responsibilities for the table. The data source is primarily responsible for providing the information to be shown in the table and the delegate's responsibility is to handle user interaction. Of course, if these objects could be of any type, the table view would not really be able to interact with them. Also, if these objects were of a specific type, we would still run into the same subclassing problem. Instead, they are defined to implement the UITableViewDelegate and UITableViewDataSource protocols respectively.

These protocols define only the methods necessary to allow the table view to properly function. This means that the delegate and dataSource properties can be any type as long as they implement the necessary methods. For example, one of the critical methods the data source must implement is tableView:numberOfRowsInSection:. This method provides the table view and an integer referring to the section that it wants to know about. It requires that an integer be returned for the number of rows in the referenced section. This is only one of multiple methods that data source must implement, but it gives you an idea of how the table view no longer has to figure out what data it contains. It simply asks the data source to figure it out.

This provides a very loosely coupled way to implement a specific table view and this same pattern is reused all over the programming world. You would be amazed at what Apple has been able to do with its table view, with very little to no pain inflicted on third party developers. The table view is incredibly optimized to handle thousands upon thousands of rows if you really wanted it to. The table has also changed a lot since the first developer kit for iOS, but these protocols have very rarely been changed except to add additional features.

Model view controller is one of the highest levels and most abstract design patterns. Variations of it are pervasive across a huge percentage of software, especially Apple's frameworks. It really can be considered the foundational pattern for how all of Apple's code is designed and therefore how most third party developers design their own code. The core concept of model view controller is that you split all of your types into three categories, often referred to as layers: model, view, and controller.

The model layer is for all of the types that represent and manipulate data. This layer is the real foundation of what your software can do for its user, so it is also often referred to as the business logic. For example, the model layer from an address book app would have types representing contacts, groups, and so on. It would also contain logic to create, delete, modify, and store those types.

The view layer is for all types involved in the display and interaction of your software. It consists of types like tables, text view, and buttons. Essentially, this layer is responsible for displaying information to the user and providing the affordances for how a user can interact with your application. The view in an address book app would consist of the displayed list of contacts, groups, and contact information.

The final layer, controller, is mostly just the glue code between the model and view layers. It will instruct the view of what to display based on the data in the model layer and it will trigger the right business logic depending on the interactions coming from the view layer. In our address book example, the controller layer would connect something such as a contact add button in the view, to the logic defined in the model for creating a new contact. It will also connect things like the on screen table view to the list of contacts in the model.

In the ideal implementation of model view controller, no model type should ever have any knowledge of the existence of a view type and no view type should know about a model type. Often, a model view controller is visualized sort of like a cake:

Model view controller

The user sees and interacts with the top of the cake and each layer only communicates with its adjacent layers. This means that all communication between the view and the model layers should go through the controller layer. At the same time, the controller layer should be pretty lightweight, because the model layer is doing the heavy lifting on the logic side of the application and the view layer is doing the heavy lifting on drawing to the screen and accepting user input.

One of the main benefits of this design pattern is that it provides a logical and consistent way to break down many pieces of software. This greatly increases your ability to share your code with other developers and understand their code. It gives everyone a frame of reference for when they try to understand another large code base that they haven't seen before. The naming of classes also gives strong clues to developers about what role a type will play in the overall system. Virtually every view class in iOS has the word "view" in it: UITableView, UIView, UICollectionViewCell, etc. Also, most of the controller layer classes that Apple provides have the word controller in them: UIViewController, UITableViewController, MFMailComposeViewController, etc. The model layer is mostly left to third party developers, other than the basic data types, since Apple isn't going to be able to help much with the business logic of your software. However, even among third party developers, these classes are often nouns named after the data they are representing or manipulating: Person, AddressBook, Publisher, and so on.

Another huge benefit of model view controller is that most components will be very reusable. You should be able to easily reuse views with different types of data like you can use a table view to display virtually any kind of data without changing the table view type and you should be able to display something like an address book in lots of different ways without changing the address book type.

As useful as this pattern is, it is also extremely hard to stick to. You will probably spend your entire development career evolving your sense for how to effectively breakdown your problems into these layers. It is often helpful to create explicit folders for each layer, forcing yourself to put every type into only one of the categories. You will also probably find yourself creating a bloated controller layer, especially in iOS, because it is often convenient to stick business logic there. More than any other design pattern, model view controller is probably the one that can be most described as something you strive for but rarely ever perfectly achieve.

Model view controller

Model view controller is one

of the highest levels and most abstract design patterns. Variations of it are pervasive across a huge percentage of software, especially Apple's frameworks. It really can be considered the foundational pattern for how all of Apple's code is designed and therefore how most third party developers design their own code. The core concept of model view controller is that you split all of your types into three categories, often referred to as layers: model, view, and controller.

The model layer is for all of the types that represent and manipulate data. This layer is the real foundation of what your software can do for its user, so it is also often referred to as the business logic. For example, the model layer from an address book app would have types representing contacts, groups, and so on. It would also contain logic to create, delete, modify, and store those types.

The view layer is for all types involved in the display and interaction of your software. It consists of types like tables, text view, and buttons. Essentially, this layer is responsible for displaying information to the user and providing the affordances for how a user can interact with your application. The view in an address book app would consist of the displayed list of contacts, groups, and contact information.

The final layer, controller, is mostly just the glue code between the model and view layers. It will instruct the view of what to display based on the data in the model layer and it will trigger the right business logic depending on the interactions coming from the view layer. In our address book example, the controller layer would connect something such as a contact add button in the view, to the logic defined in the model for creating a new contact. It will also connect things like the on screen table view to the list of contacts in the model.

In the ideal implementation of model view controller, no model type should ever have any knowledge of the existence of a view type and no view type should know about a model type. Often, a model view controller is visualized sort of like a cake:

Model view controller

The user sees and interacts with the top of the cake and each layer only communicates with its adjacent layers. This means that all communication between the view and the model layers should go through the controller layer. At the same time, the controller layer should be pretty lightweight, because the model layer is doing the heavy lifting on the logic side of the application and the view layer is doing the heavy lifting on drawing to the screen and accepting user input.

One of the main benefits of this design pattern is that it provides a logical and consistent way to break down many pieces of software. This greatly increases your ability to share your code with other developers and understand their code. It gives everyone a frame of reference for when they try to understand another large code base that they haven't seen before. The naming of classes also gives strong clues to developers about what role a type will play in the overall system. Virtually every view class in iOS has the word "view" in it: UITableView, UIView, UICollectionViewCell, etc. Also, most of the controller layer classes that Apple provides have the word controller in them: UIViewController, UITableViewController, MFMailComposeViewController, etc. The model layer is mostly left to third party developers, other than the basic data types, since Apple isn't going to be able to help much with the business logic of your software. However, even among third party developers, these classes are often nouns named after the data they are representing or manipulating: Person, AddressBook, Publisher, and so on.

Another huge benefit of model view controller is that most components will be very reusable. You should be able to easily reuse views with different types of data like you can use a table view to display virtually any kind of data without changing the table view type and you should be able to display something like an address book in lots of different ways without changing the address book type.

As useful as this pattern is, it is also extremely hard to stick to. You will probably spend your entire development career evolving your sense for how to effectively breakdown your problems into these layers. It is often helpful to create explicit folders for each layer, forcing yourself to put every type into only one of the categories. You will also probably find yourself creating a bloated controller layer, especially in iOS, because it is often convenient to stick business logic there. More than any other design pattern, model view controller is probably the one that can be most described as something you strive for but rarely ever perfectly achieve.

The final type of design patterns we will discuss is called creational patterns. These patterns relate to the initialization of new objects. At first, the initialization of an object probably seems simple and not a very important place to have design patterns. After all, we already have initializers. However, in certain circumstances, creational patterns can be extremely helpful.

The first patterns we will discuss are the singleton and shared instance patterns. We are discussing them together because they are extremely similar. First we will discuss shared instance, because it is the less strict form of the singleton pattern.

The idea of the shared instance pattern is that you provide an instance of your class to be used by other parts of your code. Let's look at a quick example of this in Swift:

Here, we have a simple address book class but we are providing a static constant called sharedInstance that any other code can use without having to create its own instance. This is a very convenient way to allow otherwise separate code to collaborate. Instead of having to pass around a reference to the same instance all over your code, any code can refer the shared instance right through the class itself:

Now, the different thing about the singleton pattern is that you would write your code in such a way that it is not even possible to create a second instance of your class. Even though our preceding address book class provides a shared instance, there is nothing to stop someone from creating their own instance using the normal initializers. We could pretty easily change our address book class to a singleton instead of a shared instance, as shown:

Besides changing the name of the static constant, the only difference with this code is that we declared the initializers as private. This makes it so that no code outside of this file can use the initializer and therefore, no code outside of this file can create a new instance.

The singleton pattern is great for when multiple instances of the same class are going to cause a problem. This is especially important for classes that represent a finite physical resource but it can also be a way to simplify a class that would be more difficult and unnecessary to implement in a way that would allow multiple instances. For example, there isn't actually much of a reason to ensure there is only ever one address book in an application. Perhaps the user will want to have two address books: one for business and one for personal. They should be able to operate independently as long as they are working from a different file, but maybe in your application you know that there will only ever be a single address book and it always has to be driven by a single file. Instead of requiring your code to create an address book with a specific file path, and instead of dealing with the danger of having multiple instances reading and writing to the same file, you can use the singleton version above and have the file path be fixed.

In fact, the singleton and shared instance patterns are so convenient that many developers over use them. So let's discuss some of the drawbacks of these patterns. It is nice to be able to access an instance from anywhere, but when it is easy to do so, it is also easy to create a very complex web of dependencies on that object. That goes against the principle of low coupling that we are trying to achieve. Imagine trying to change a singleton class when you have 20 different pieces of code all using it directly.

Using these patterns can also create hidden dependencies. Usually, it is pretty clear what dependencies an instance has based on what it must be initialized with, but a singleton or shared instance does not get passed into the initializer, so it can often go unnoticed as a dependency. Even though there is some initial extra overhead to passing an object into an initializer, it will often reduce the coupling and maintain a clearer picture of how your types interact. The bottom line is, like with any other pattern, think carefully about each use of the singleton and shared instance patterns and be sure it is the best tool for the job.

The final pattern we will discuss here is called abstract factory. It is based on a simpler pattern called factory. The idea of a factory pattern is that you implement an object for creating other objects, much like you would create a factory for assembling cars. The factory pattern is great when the initializing of a type is very complex or you want to create a bunch of similar objects. Let's take a look at the second scenario. What if we were creating a two-player ping-pong game and we had some scenario in the game where we would add additional balls that a specific player needed to keep in play? The ball class might look something like this:

Every time we needed a new ball we could assign a new color and owning player to it. Or, we could create a separate ball factory for each player:

Now, we could pass this factory into whatever object is responsible for handling the ball creation event and that object is no longer responsible for determining the color of the ball or any other properties we might want. This is great for reducing the number of responsibilities that object has and also keeps the code very flexible to add additional ball properties in the future without having to change the ball creation event object.

An abstract factory is a special form of factory where the instances the factory creates may be one of many subclasses of a single other class. A great example of this would be an image creation factory. As we discussed in Chapter 3, One Piece at a Time – Types, Scopes, and Projects, computers have an enormous number of ways to represent images. In that chapter we hypothesized having a superclass called just "Image" that would have a subclass for each type of image. This would help us write classes to handle any type of image very easily by always having them work with the image superclass. Similarly, we could create an image factory that would virtually eliminate any need for an external type to know anything about the different types of images. We could design an abstract factory that takes the path to any image, loads the image into the appropriate subclass, and returns it simply as the image superclass. Now, neither the code that loads an image, nor the code that uses the image, needs to know what type of image they are dealing with. All of the complexity of different image representations is abstracted away inside the factory and the image class hierarchy. This is a huge win for making our code easier to understand and more maintainable.

Singleton/shared instance

The

first patterns we will discuss are the singleton and shared instance patterns. We are discussing them together because they are extremely similar. First we will discuss shared instance, because it is the less strict form of the singleton pattern.

The idea of the shared instance pattern is that you provide an instance of your class to be used by other parts of your code. Let's look at a quick example of this in Swift:

Here, we have a simple address book class but we are providing a static constant called sharedInstance that any other code can use without having to create its own instance. This is a very convenient way to allow otherwise separate code to collaborate. Instead of having to pass around a reference to the same instance all over your code, any code can refer the shared instance right through the class itself:

Now, the different thing about the singleton pattern is that you would write your code in such a way that it is not even possible to create a second instance of your class. Even though our preceding address book class provides a shared instance, there is nothing to stop someone from creating their own instance using the normal initializers. We could pretty easily change our address book class to a singleton instead of a shared instance, as shown:

Besides changing the name of the static constant, the only difference with this code is that we declared the initializers as private. This makes it so that no code outside of this file can use the initializer and therefore, no code outside of this file can create a new instance.

The singleton pattern is great for when multiple instances of the same class are going to cause a problem. This is especially important for classes that represent a finite physical resource but it can also be a way to simplify a class that would be more difficult and unnecessary to implement in a way that would allow multiple instances. For example, there isn't actually much of a reason to ensure there is only ever one address book in an application. Perhaps the user will want to have two address books: one for business and one for personal. They should be able to operate independently as long as they are working from a different file, but maybe in your application you know that there will only ever be a single address book and it always has to be driven by a single file. Instead of requiring your code to create an address book with a specific file path, and instead of dealing with the danger of having multiple instances reading and writing to the same file, you can use the singleton version above and have the file path be fixed.

In fact, the singleton and shared instance patterns are so convenient that many developers over use them. So let's discuss some of the drawbacks of these patterns. It is nice to be able to access an instance from anywhere, but when it is easy to do so, it is also easy to create a very complex web of dependencies on that object. That goes against the principle of low coupling that we are trying to achieve. Imagine trying to change a singleton class when you have 20 different pieces of code all using it directly.

Using these patterns can also create hidden dependencies. Usually, it is pretty clear what dependencies an instance has based on what it must be initialized with, but a singleton or shared instance does not get passed into the initializer, so it can often go unnoticed as a dependency. Even though there is some initial extra overhead to passing an object into an initializer, it will often reduce the coupling and maintain a clearer picture of how your types interact. The bottom line is, like with any other pattern, think carefully about each use of the singleton and shared instance patterns and be sure it is the best tool for the job.

The final pattern we will discuss here is called abstract factory. It is based on a simpler pattern called factory. The idea of a factory pattern is that you implement an object for creating other objects, much like you would create a factory for assembling cars. The factory pattern is great when the initializing of a type is very complex or you want to create a bunch of similar objects. Let's take a look at the second scenario. What if we were creating a two-player ping-pong game and we had some scenario in the game where we would add additional balls that a specific player needed to keep in play? The ball class might look something like this:

Every time we needed a new ball we could assign a new color and owning player to it. Or, we could create a separate ball factory for each player:

Now, we could pass this factory into whatever object is responsible for handling the ball creation event and that object is no longer responsible for determining the color of the ball or any other properties we might want. This is great for reducing the number of responsibilities that object has and also keeps the code very flexible to add additional ball properties in the future without having to change the ball creation event object.

An abstract factory is a special form of factory where the instances the factory creates may be one of many subclasses of a single other class. A great example of this would be an image creation factory. As we discussed in Chapter 3, One Piece at a Time – Types, Scopes, and Projects, computers have an enormous number of ways to represent images. In that chapter we hypothesized having a superclass called just "Image" that would have a subclass for each type of image. This would help us write classes to handle any type of image very easily by always having them work with the image superclass. Similarly, we could create an image factory that would virtually eliminate any need for an external type to know anything about the different types of images. We could design an abstract factory that takes the path to any image, loads the image into the appropriate subclass, and returns it simply as the image superclass. Now, neither the code that loads an image, nor the code that uses the image, needs to know what type of image they are dealing with. All of the complexity of different image representations is abstracted away inside the factory and the image class hierarchy. This is a huge win for making our code easier to understand and more maintainable.

Abstract factory

The final

pattern we will discuss here is called abstract factory. It is based on a simpler pattern called factory. The idea of a factory pattern is that you implement an object for creating other objects, much like you would create a factory for assembling cars. The factory pattern is great when the initializing of a type is very complex or you want to create a bunch of similar objects. Let's take a look at the second scenario. What if we were creating a two-player ping-pong game and we had some scenario in the game where we would add additional balls that a specific player needed to keep in play? The ball class might look something like this:

Every time we needed a new ball we could assign a new color and owning player to it. Or, we could create a separate ball factory for each player:

Now, we could pass this factory into whatever object is responsible for handling the ball creation event and that object is no longer responsible for determining the color of the ball or any other properties we might want. This is great for reducing the number of responsibilities that object has and also keeps the code very flexible to add additional ball properties in the future without having to change the ball creation event object.

An abstract factory is a special form of factory where the instances the factory creates may be one of many subclasses of a single other class. A great example of this would be an image creation factory. As we discussed in Chapter 3, One Piece at a Time – Types, Scopes, and Projects, computers have an enormous number of ways to represent images. In that chapter we hypothesized having a superclass called just "Image" that would have a subclass for each type of image. This would help us write classes to handle any type of image very easily by always having them work with the image superclass. Similarly, we could create an image factory that would virtually eliminate any need for an external type to know anything about the different types of images. We could design an abstract factory that takes the path to any image, loads the image into the appropriate subclass, and returns it simply as the image superclass. Now, neither the code that loads an image, nor the code that uses the image, needs to know what type of image they are dealing with. All of the complexity of different image representations is abstracted away inside the factory and the image class hierarchy. This is a huge win for making our code easier to understand and more maintainable.

Good programming is about more than just grand, universal concepts of how to write effective code. The best programmers know how to play to the strengths of the tools at hand. We are now going to move from looking at the core tenants of programming design to some of the gritty details of enhancing your code with the power of Swift.

The first thing we will look at is making effective use of the associated value of an enumeration. Associated values are a pretty unique feature of Swift, so they open up some pretty interesting possibilities.

We have already seen in Chapter 3, One Piece at a Time – Types, Scopes, and Projects that we can use an enumeration with associated values to represent a measurement like distance in multiple measurement systems:

enum Height {
    case Imperial(feet: Int, Inches: Double)
    case Metric(meters: Double)
    case Other(String)
}

We can generalize this use case as using an enumeration to flatten out a simple class hierarchy. Instead of the enumeration, we could have created a height superclass or protocol with subclasses for each measurement system. However, this would be a more complex solution and we would lose the benefits of using a value type instead of a reference type. The enumeration solution is also very compact, making it very easy to understand at a glance instead of having to analyze how multiple different classes fit together.

Let's look at an even more complex example. Let's say we want to create a fitness app and we want to be able to track multiple types of workouts. Sometimes people workout to do a certain number of repetitions of various movements; other times they are just going for a certain amount of time. We could create a class hierarchy for this, but an enumeration with associated values works great:

enum Workout {
    case ForTime(seconds: Int)
    case ForReps(movements: [(name: String, reps: Int)])
}

Now, when we want to create a workout, we only need to define values relevant to the type of workout we are interested in without having to use any classes at all.

Another great use of enumerations with associated values is to represent the state of something. The simplest example of this would be a result enumeration that can either contain a value or an error description if an error occurs:

This allows us to write a function that can fail and give a reason that it failed:

This is an alternative to normal error handling and can make sense for functions where the failure case is treated similarly to a success case instead of as a rare exception.

A slightly more complex idea is to use an enumeration to represent a process that will go through various stages over time, often called a state machine. We could write an enumeration for the process of a download:

While the download is in progress we can access how complete it is and once it is complete we can access the data that it downloaded. This information is only accessible when it is applicable. This enumeration will also make it easier to make sure our download is always in a reasonable and clearly defined state. There is no possibility for a middle ground where, for example, the download might be complete but the data hasn't been processed yet. If we wanted to represent an additional processing step, we could easily add another case and it would be clear from then on out that a download will go through that additional state.

Replacing class hierarchies

We

have already seen in Chapter 3, One Piece at a Time – Types, Scopes, and Projects that we can use an enumeration with associated values to represent a measurement like distance in multiple measurement systems:

enum Height {
    case Imperial(feet: Int, Inches: Double)
    case Metric(meters: Double)
    case Other(String)
}

We can generalize this use case as using an enumeration to flatten out a simple class hierarchy. Instead of the enumeration, we could have created a height superclass or protocol with subclasses for each measurement system. However, this would be a more complex solution and we would lose the benefits of using a value type instead of a reference type. The enumeration solution is also very compact, making it very easy to understand at a glance instead of having to analyze how multiple different classes fit together.

Let's look at an even more complex example. Let's say we want to create a fitness app and we want to be able to track multiple types of workouts. Sometimes people workout to do a certain number of repetitions of various movements; other times they are just going for a certain amount of time. We could create a class hierarchy for this, but an enumeration with associated values works great:

enum Workout {
    case ForTime(seconds: Int)
    case ForReps(movements: [(name: String, reps: Int)])
}

Now, when we want to create a workout, we only need to define values relevant to the type of workout we are interested in without having to use any classes at all.

Another great use of enumerations with associated values is to represent the state of something. The simplest example of this would be a result enumeration that can either contain a value or an error description if an error occurs:

This allows us to write a function that can fail and give a reason that it failed:

This is an alternative to normal error handling and can make sense for functions where the failure case is treated similarly to a success case instead of as a rare exception.

A slightly more complex idea is to use an enumeration to represent a process that will go through various stages over time, often called a state machine. We could write an enumeration for the process of a download:

While the download is in progress we can access how complete it is and once it is complete we can access the data that it downloaded. This information is only accessible when it is applicable. This enumeration will also make it easier to make sure our download is always in a reasonable and clearly defined state. There is no possibility for a middle ground where, for example, the download might be complete but the data hasn't been processed yet. If we wanted to represent an additional processing step, we could easily add another case and it would be clear from then on out that a download will go through that additional state.

Concisely representing state

Another great

use of enumerations with associated values is to represent the state of something. The simplest example of this would be a result enumeration that can either contain a value or an error description if an error occurs:

This allows us to write a function that can fail and give a reason that it failed:

This is an alternative to normal error handling and can make sense for functions where the failure case is treated similarly to a success case instead of as a rare exception.

A slightly more complex idea is to use an enumeration to represent a process that will go through various stages over time, often called a state machine. We could write an enumeration for the process of a download:

While the download is in progress we can access how complete it is and once it is complete we can access the data that it downloaded. This information is only accessible when it is applicable. This enumeration will also make it easier to make sure our download is always in a reasonable and clearly defined state. There is no possibility for a middle ground where, for example, the download might be complete but the data hasn't been processed yet. If we wanted to represent an additional processing step, we could easily add another case and it would be clear from then on out that a download will go through that additional state.

Another powerful feature that we briefly covered in Chapter 3, One Piece at a Time – Types, Scopes, and Projects is the ability to extend existing types. We saw that we could add an extension to the string type that would allow us to repeat the string multiple times. Let's look at a more practical use case for this and discuss its benefits in terms of improving our code.

Perhaps we are creating a grade-tracking program where we are going to be printing out a lot of percentages. A great way to represent percentages is by using a float with a value between zero and one. Floats are great for percentages because we can use the built-in math functions and they can represent pretty granular numbers. The hurdle to cross when using a float to represent a percentage is printing it out. If we simply print out the value, it will most likely not be formatted the way we would want. People prefer percentages to be out of 100 and have a percent symbol after it.

Worst case scenario, we are going to write something, such as print("\(myPercent * 100)%"), every time we need to print out a percentage. This is not very flexible; what if we wanted to tweak all percentage outputs to have leading spaces, so it prints out right aligned? We would have to go through and change every print statement. Instead, we could write our own function like printPercentage. This will allow us to share the same code in lots of places.

This is a good step, but we can do one better using Swift's ability to extend system types. If we have an arbitrary function called printPercentage, we are going to have a hard time remembering it is there and other developers will have a hard time discovering it in the first place. It would be much nicer if we could easily get a printable version of a float directly from the float itself. We can make this possible by adding an extension to Float:

Now we can use auto-complete to help us remember what formats we have defined for a float. Over time, you will probably develop a collection of useful and generic extensions like this that are extremely reusable because they are independent of any of your other program specific code. Writing these in such a reusable way makes it very easy to bring them into a new program, greatly accelerating each new project you start.

However, you do want to be careful that you don't end up creating too many extensions. For more complex situations, it is often more appropriate to use the composite pattern instead. For example, we could have written this as a Percent type that can be constructed with a Float:

In this case it may not warrant the complexity of its own class, but you should at least consider how you might want to extend the idea of a percentage in the future.

One feature we have not yet discussed is the concept of lazy properties. Marking a property as lazy allows Swift to wait to initialize it until the first time it is accessed. This can be useful in at least a few important ways.

Avoiding unnecessary memory usage

The
Avoiding unnecessary processing

We can
Localizing logic to the concerned property

An

We have covered a lot of very large design concepts in a short period of time. We have looked at a number of specific design patterns, that help reduce the complexity of our code by reducing inter-object dependencies, commonly referred to as low coupling, and increasing the simplicity in which those objects work together, otherwise referred to as high cohesion.

We learned that there are three types of design patterns that focus on fixing different types of problems. Behavioral patterns help objects communicate with each other better, structural patterns facilitate the breaking down of complex structures into smaller and simpler ones, and creational patterns help with the initialization of new objects.

We also looked at some very specific features of Swift and how they can help us achieve similar goals to the ones we achieve with design patterns. We saw how to use enumerations with associated values to reduce the complexity of our type system and represent state better; we used extensions to system types to reduce the amount of code we write, and we wrote more efficient and understandable code using lazy properties.

As I said in the beginning, design patterns is a huge topic and not something you will master quickly, if ever. Figuring out how to best use the feature of a specific language is also a huge topic. I strongly recommend you use this chapter as a reference when you start to develop larger software and want to find ways to make it less complex. I also strongly encourage you to research more patterns and try to implement them on your own. Each design pattern is another tool in your toolbox. The more tools you have and the more experienced you are with each of them, the better you will be able to choose the right tool for the right job. That is the art of programming.

Now we are ready for the next chapter, where we will take a step back into the past to look at Objective-C so that we can leverage the vast resources targeted at Objective-C that are still very relevant to us as Swift developers.