Waldo sessions now support scripting! – Learn more
App Development

Stacks in Swift: What They Are and How to Use Them

Juan Reyes
Juan Reyes
Stacks in Swift: What They Are and How to Use Them
July 12, 2022
8
min read

Terms like arrays, graphs, trees, and linked lists are commonly some of the first things a student would be tasked with learning during their first few steps in the programming world. And to many, these concepts will pose a challenge to wrap their head around, despite the similarity to common everyday ideas.

One such concept is the stack. And if you were to take it at face value and realized it's also a data structure, you could pretty much take your assumption as pretty accurate to its real-life counterpart. However, there are a lot of intricacies and nuances that you need to understand in order to take advantage of this data structure in your programming journey.

So, in this post, we'll be exploring the stack data structure in Swift and what it offers us as one of the fundamental data structures in programming.

To achieve this, we'll first provide you with a brief definition of what a stack is and explain why it's so important. Then, we'll put the theory into action with some swifty (see what I did there?) stack examples you can play with.

Finally, we'll show you some useful extensions you can apply to visualize and handle the data easier on your stacks in Swift.

Alright, let's get into it.

What Are Swift Stacks?

So, what comes to mind when you think of a stack? A pile of dishes? A stash of cash? Maybe a heap of homework papers? Funny how there are so many words for the same idea.

Well, you can pretty much apply the same idea to data, and you would've described a stack data structure pretty accurately. The only difference is how you can interact with it.

In Swift, a stack is an abstract collection that allows you to organize data in a particular order. This concept is based on the idea that you can organize information similarly to things in the real world.

Much like how you can only put items in and out of a stack in a specific order, data on a stack data structure can only be interacted with in one particular order, known as last-in-first-out (LIFO).

In contrast, a data structure like a queue, which also collects items linearly, allows you to add items one after the other, but when retrieving them, you get the items at the front. This follows the first-in-first-out behavior.

In Swift, a stack is an abstract collection that allows you to organize data in a particular order.

Stack Operations

The operations for adding and removing data to the stack are known as push and pop, respectively. Additionally, the peek operation allows you to see the last added item without removing it from the collection. These operations are clear analogs to how you would only be able to pull the previously added item into a pile of objects.

To illustrate, here's a visual representation of their functionality.

Push:

stack push

As you can see, you can add items in a linear order, one on top of the other. The push operation adds or pushes an item in the stack.

Pop:

stack pop

Here, the item that's accessible is the one at the top, so popping will result in getting the item that was added last—in this case, 5.

Peek:

stack peek

The peek operation lets you see what item is at the top of the stack. In this case, the stack is kept the same.

Why Are Stacks Important?

Now, why would you want such a specific structure in the first place?

Well, it turns out that, in many algorithms, you might want to add objects to a list and then pull them off in this specific order. As with most data structures, the order in which you add and remove objects matters significantly and is often what makes them so powerful and valuable.

One of the essential features that stacks offer is backtracking. As you can already imagine, this allows for features like "undo" on document processors like Word or "go back" in browsers to work efficiently. Additionally, developers can use stacks to implement recursive solutions iteratively for a more programming-specific example.

Alright, enough theory. Let's see an implementation of stacks in Swift.

As with most data structures, the order in which you add and remove objects matters significantly and is often what makes them so powerful and valuable.

Swift Stacks in Action

If you want to follow along with us, open up a playground on XCode and continue reading.

OK, so a stack's basic structure has the same properties as an array, which is a type that already exists in Swift. So, you can use it as the basis of your stack.

Here's a simple stack skeleton.


struct Stack {
    fileprivate var array: [String] = []
}

Simple and clean.

Now, let's add the first operation, push.

Do you remember the behavior of a push?

That's right. You add an item to the stack or, in this case, the array.


struct Stack {
    fileprivate var array: [String] = []
    mutating func push(_ item: String) {
        array.append(item)
    }
}

Great, let's move to the next operation, pop.

In this case, you pull the last item added in the array, and you need to make sure that the item is removed, so the array must mutate.


struct Stack {
    fileprivate var array: [String] = []
    mutating func push(_ item: String) {
        array.append(item)
    }
    mutating func pop() -> String? {
        if array.isEmpty {
            return nil
        }
        return array.remove(at: array.count - 1)
    }
}

Good. However, you can simplify this further with Swift's "popLast()" array function, which essentially does all this for us.


struct Stack {
    fileprivate var array: [String] = []
    mutating func push(_ item: String) {
        array.append(item)
    }
    mutating func pop() -> String? {
        return array.popLast()
    }
}

Additionally, this function already handles the case where the array is empty and returns nil.

Finally, the peek operation is similar to the pop function, but it doesn't mutate the array. In this case, you can use the ".last" property of the array type in Swift.


struct Stack {
    fileprivate var array: [String] = []
    mutating func push(_ item: String) {
        array.append(item)
    }
    mutating func pop() -> String? {
        return array.popLast()
    }
    func peek() -> String? {
        return array.last
    }
}

And that's about it.

To test your code, go ahead and create a new stack, push some items, and then peek and pop them.


struct Stack {
    fileprivate var array: [String] = []
    mutating func push(_ item: String) {
        array.append(item)
    }
    mutating func pop() -> String? {
        return array.popLast()
    }
    func peek() -> String? {
        return array.last
    }
}
var myStack = Stack()
myStack.push("1")
myStack.push("2")
myStack.push("3")
myStack.push("4")
myStack.push("5")
myStack.peek() // 5
myStack.pop() // 5
myStack.pop() // 4
myStack.pop() // 3

Great work!

Now, what if you want to be able to visualize the item on your stack?

Let's see how to extend the stack to add more features.

Adding Features to Stacks in Swift

If you want to be able to visualize the whole stack, all you have to do is add an extension to the stack class and print its content. Here's a simple example expanding on the code you've already created.


struct Stack {
    fileprivate var array: [String] = []
    mutating func push(_ item: String) {
        array.append(item)
    }
    mutating func pop() -> String? {
        return array.popLast()
    }
    func peek() -> String? {
        return array.last
    }
}
extension Stack: CustomStringConvertible {
  var description: String {
    return "^Stack^\n" + array.reversed().joined(separator: "\n") + "\n-------\n"
  }
}
var myStack = Stack()
myStack.push("1")
myStack.push("2")
myStack.push("3")
myStack.push("4")
myStack.push("5")
myStack.peek() // 5
print(myStack.description)
myStack.pop() // 5
myStack.pop() // 4
myStack.pop() // 3

What this code does is modify the default print method that exists in all Swift objects and format the output to your specification. In this case, you're collecting all the items in the array as strings, joining them with the line break special character into a single string, and appending indicators of the top and bottom of the stack.

I know that was a mouthful, but you'll understand once you run it. Go ahead.

screenshot of code

Nice!

What's Next?

Data structures. The bread and butter of computing. An essential part of the journey of learning programming and a vast sea of intricate complexity.

It would be nearly impossible to understate the importance of data structures in advancing technology and the industry without exposing how little you understand it.

As we've learned, the stack data structure is an essential building block of what we understand the modern technology framework to be today. Therefore, understanding it and its capabilities is critical to being proficient and productive with your work, no matter what you try to achieve.

Nevertheless, you must use a reliable testing workflow like Waldo's no-code testing workflow solution to ensure that your work is free of bugs.

And the best part about using Waldo is that there's no need to create complicated and messy testing workflows. Just set it up, and you're good to go.

You can learn more about it here.

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.