Skip to main content

Design Patterns in Swift: Command Pattern

Welcome to a series of posts dedicated to learning about design patterns. Whilst a lot of the ideas are code-agnostic, we’re aiming to show you how to implement them in Swift (Swift 3.0 as of the time of writing). Each post is independent of each other and all code for the projects will be available here on Git.


iPhone Springboard

Okay, so for todays example, picture your an iPhone, specifically the Springboard on the iPhone. You have a grid of apps that a user can tap at any point and execute. You also have a home button which closes your apps (okay, it doesn't, it pushes them to the background, but stay with us). Each app runs its own specific list of commands when it runs and when it closes.
At the moment, when you — the iPhone — look at the Weather and Clock app, you see these functions exposed:


Well, thats confusing

How do you start an app? Well I guess you would call getWeatherData() first on the WeatherApp, and then maybe showWeatherAnimation(). On the ClockApp, you would just have to call showClock(). A bit confusing for the poor iPhone. Two completely different objects, with no real way of knowing what to do without having prior knowledge of how the objects work.
What the iPhone needs to be able to do, is to encapsulate those commands into another function so that it knows how to launch the app, without having to have into intricate knowledge on how the app works. This is solvable with the Command pattern. (This example was really a stretch. The iPhone will use a much more complicated system is real life, but it provides a nice visual idea that we can all picture in our heads to demonstrate how the pattern works!)
What the Command pattern allows us to do is to turn our Commands into objects that will execute the correct list of functions depending on the object, without having to modify the object itself (it would be a pain if we had to ask the developers of these two applications to change their codebase). For instance, we would create a class called WeatherAppOpen that would conform to a Command protocol, and would execute getWeatherData() and showWeatherAnimation() when a generic execute() function is called.
This is what the Command pattern for the iPhone’s Springboard looks like in UML form:



The Springboard never communicates directly with the WeatherApp because the necessary commands are abstracted to a common generic method, meaning the Springboard only needs to be aware of one method.
To start, create a new project in Xcode. We won’t be touching anything in UIKit so create a macOS Terminal project.
We’ll create the Command protocol first that all of our command classes will conform to. Its relatively simple, and just contains the execute() function that the Springboard will talk to.


Next, we’ll create our WeatherApp and ClockApp classes. These classes will just contain some boilerplate methods that print out to the console so we could see what our theoretical Springboard would be doing. They will look like this:


We now need to access those methods via the Command protocol. To do this, we create the object as the type of Command we wish to complete I.E open or close the app. Starting with opening the Weather app, we’ll create WeatherAppOpenCommand.


We invoke the class by passing through an instance of the Weather App (if this was real life, that would probably be a Singleton in the case of the iPhone — post coming soon!). When execute() is called, we then launch the app, using the specific commands to the Weather App. We do the same with closing the Weather App, which looks like this:


Starting to get the picture? We can then build the Clock App commands in exactly the same way, but call the methods specific to the Clock App:


We can now look at building our pretend (and very simplistic) Springboard.
The Springboard needs to be able to hold an array of open and close commands (our apps). It then needs to be able to execute a command at specific index if an app is available. It will look like so:


The setCommand function allows us to effetely place an app at an index on the Springboard, and the open/closeApp functions allow us to execute the correct command at the index provided.
So now we’ll build the client (or the iPhone in this case).


We create an instance of the Springboard, an instance of the Weather App, and an instance of the Clock App. We set the commands using the Open/Close objects relative to each app, and pass through the instance of the app to the relevant commands.
Run the program, and you’ll get an output that looks like this:
Hurray you built an iPhone*! You’re running the apps, in an expandable, encapsulated way, that the Springboard knows nothing about!

Comments

Popular posts from this blog

Alamofire vs URLSession

Alamofire vs URLSession: a comparison for networking in Swift Alamofire and URLSession both help you to make network requests in Swift. The URLSession API is part of the foundation framework, whereas Alamofire needs to be added as an external dependency. Many  developers  doubt  whether it’s needed to include an extra dependency on something basic like networking in Swift. In the end, it’s perfectly doable to implement a networking layer with the great URLSession API’s which are available nowadays. This blog post is here to compare both frameworks and to find out when to add Alamofire as an external dependency. Build better iOS apps faster Looking for a great mobile CI/CD solution that has tons of iOS-specific tools, smooth code signing, and even real device testing? Learn more about Bitrise’s iOS specific solutions! This shows the real power of Alamofire as the framework makes a lot of things easier. What is Alamofire? Where URLSession...

Swift Tool Belt, Part 1: Adding a Border, Corner Radius, and Shadow to a UIView with Interface Builder

During my iOS work, I’ve assembled a set of code that I bring with me on every iOS project. I’m not talking about large frameworks or CocoaPods here. These are smaller Swift extensions or control overrides that are applicable to many projects. I think of them as my tool belt. In this post, I’ll show you an extension that will add a border, a corner radius, and a shadow to any UIView, UIButton, or UILabel and allow you to preview what it will look like in Interface Builder. Back in 2014, I wrote a blog post on Expanding User-Defined Runtime Attributes in Xcode where I added a border, corner radius, and shadow to a UIView using Interface Builder’s user-defined runtime attributes. This solution had no type checking—you had to type the property you wanted to modify by hand and often had to look up what it was called. You also had to run your project in order to see the effect of the runtime attribute. Starting with Xcode 6 , there is a new mech...

Frame vs Bounds in iOS

This article is a repost of an answer I wrote on Stack Overflow . Short description frame = a view’s location and size using the parent view’s coordinate system ( important for placing the view in the parent) bounds = a view’s location and size using its own coordinate system (important for placing the view’s content or subviews within itself) Details To help me remember frame , I think of a picture frame on a wall . The picture frame is like the border of a view. I can hang the picture anywhere I want on the wall. In the same way, I can put a view anywhere I want inside a parent view (also called a superview). The parent view is like the wall. The origin of the coordinate system in iOS is the top left. We can put our view at the origin of the superview by setting the view frame’s x-y coordinates to (0, 0), which is like hanging our picture in the very top left corner of the wall. To move it right, increase x, to move it down increase y. To help me remember bound...