Assigning an expression to a variable with the same name
New in Swift 5.4: It’s now possible to create a local variable that’s assigned to an expression that has the same name, without having to manually disambiguate with self
.
For example, the following ItemListViewController
has a method that lets us retrieve an Item
for a given IndexPath
, which we’ve chosen to simply call item(at:)
:
class ItemListViewController: UIViewController {
...
private func item(at indexPath: IndexPath) -> Item {
...
}
}
When using Swift 5.3 and earlier, if we wanted to call the above method and assign its result to a local let
or var
that’s also called item
, we’d then have to prefix our method call with self
in order for the compiler to be able to separate the two — like this:
class ItemListViewController: UIViewController {
...
private func showDetailViewForItem(at indexPath: IndexPath) {
let item = self.item(at: indexPath)
...
}
}
Starting in Swift 5.4, however, that’s no longer required, and the compiler will now automatically understand that the right-hand item
symbol refers to a call to our method, regardless of whether we refer to it using self
:
class ItemListViewController: UIViewController {
...
private func showDetailViewForItem(at indexPath: IndexPath) {
let item = item(at: indexPath)
...
}
}
Perhaps my favorite way of using this new syntax feature is when writing unit tests for asynchronous code, which typically involves creating XCTestExpectation
instances using the built-in expectation
API. Because the most natural name for such expectations is often simply expectation
, it’s really nice to now be able to do the following:
class ItemLoaderTests: XCTestCase {
...
func testLoadingItem() {
let expectation = expectation(description: "Loading item")
...
}
}
Another type of situation in which the above feature could come in handy is when we want to create a local, mutable copy of a property. That can now also be done without having to use self
when referring to the property that we’re copying — for example like this:
struct Item {
var title: String
var prefix: String?
var suffix: String?
func fullTitle() -> String {
var title = title
if let prefix = prefix {
title = prefix + title
}
if let suffix = suffix {
title += suffix
}
return title
}
}
Granted, this might not be a revolutionary new syntax feature that will completely change the way we write Swift code — but hey, not every feature or change needs to be. I personally think that these kinds of “quality of life” improvements are incredibly welcome, and can make certain kinds of code feel quite a bit more lightweight.