Articles, podcasts and news about Swift development, by John Sundell.

Assigning an expression to a variable with the same name

Published on 14 May 2021

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.