Every now and then, I take some time out of my day to explore something about the Swift language that I don't know yet. There is a lot left to explore. I document my findings in a series I named What The Swift. If you are curious about the more subtle details of the Swift language, then this series is for you.
In the previous episodes of this series, we explored AnyObject
and Any
. Another keyword you encounter frequently in Swift is Void
. What is Void
? That is the focus of this installment of What The Swift.
Get Ready to Play
Open Xcode and and create a new playground. Choose the Blank template from the iOS section. Name the playground What The Swift, tell Xcode where you'd like to save the playground, and click Create.
Exploring the Swift Standard Library
Remove the contents of the playground and add an import statement for Foundation.
import Foundation
Let's start by defining a function, sayHello()
, that accepts no arguments and returns nothing. This should look familiar.
import Foundation
func sayHello() {
}
The function declaration indicates that it returns nothing, but that isn't true. A function that doesn't specify a return type returns Void
. This means we can update the function declaration like this.
import Foundation
func sayHello() -> Void {
}
The functionality of the sayHello()
function hasn't changed. That is important to understand. What changed is that we explicitly indicate that the return type of sayHello()
is Void
. This brings us to the question of this episode. What does Void
mean in Swift?
What Is Void in Swift?
Plenty of languages define Void
. The question is how Swift defines Void
. Press Command and click Void
in the function declaration. This takes you to the definition of Void
in the Standard Library. The answer is pretty clear. Take a moment to let this sink in.
/// The return type of functions that don't explicitly specify a return type,
/// that is, an empty tuple `()`.
///
/// When declaring a function or method, you don't need to specify a return
/// type if no value will be returned. However, the type of a function,
/// method, or closure always includes a return type, which is `Void` if
/// otherwise unspecified.
///
/// Use `Void` or an empty tuple as the return type when declaring a closure,
/// function, or method that doesn't return a value.
///
/// // No return type declared:
/// func logMessage(_ s: String) {
/// print("Message: \(s)")
/// }
///
/// let logger: (String) -> Void = logMessage
/// logger("This is a void function")
/// // Prints "Message: This is a void function"
public typealias Void = ()
As the documentation explains, Void
is a type alias for ()
, an empty tuple. This means we can replace Void
with an empty tuple in the function declaration of sayHello()
.
import Foundation
func sayHello() -> () {
}
There are a few details I want to highlight. First, a function, method, or closure always returns something. Second, if a function, method, or closure returns nothing, it actually means that it returns an empty tuple. In other words, a function, method, or closure always returns a tuple, but it is possible that the tuple is empty.
When Should You Use Void?
The documentation states that a function that doesn't specify a return type returns an empty tuple. You may be wondering why you would ever use Void
. The documentation provides the answer. You use Void
to declare the type of a function, method, or closure. Take a look at this example.
internal final class SessionManager {
// MARK: - Properties
var didSignOut: (() -> Void)?
// MARK: - Helper Methods
private func destroySession() {
didSignOut?()
}
}
We declare a class with name SessionManager
. The SessionManager
class declares a property with name didSignOut
. The didSignOut
property has an optional function type. The function accepts no arguments and returns Void
. We cannot omit Void
in this example. If we remove Void
, then the compiler no longer understands the meaning of the property declaration. The compiler is smart, but it doesn't have enough information to infer what the type of the didSignOut
property is.
By removing Void
from the property declaration, we rendered the contents of the playground invalid Swift. There is one change we can make, though. Because Void
is a type alias for an empty tuple, we can replace Void
with an empty tuple. The compiler is fine with that.
internal final class SessionManager {
// MARK: - Properties
var didSignOut: (() -> ())?
// MARK: - Helper Methods
private func destroySession() {
didSignOut?()
}
}
Notice that we have a pair of parentheses, a return arrow, and another pair of parentheses. It is important to understand that the second pair of parentheses is an empty tuple, but the first pair of parentheses isn't. This is clear if we try to replace the first pair of parentheses with the Void
keyword.
What The Swift
I hope this episode has answered any questions you had about the Void
keyword. As you can see, the Void
keyword is nothing more than a type alias for an empty tuple. Some answers don't need to be complicated.