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.

Support Swift by Sundell by checking out this sponsor:

Essential Developer

Essential Developer: Learn the most up-to-date techniques and strategies for testing new and legacy Swift code in this free practical course for developers who want to become complete senior iOS developers. This virtual event includes lectures, mentoring sessions, and step-by-step instructions. Click to learn more.