Xcode 8 / Swift 3: "Expression of type UIViewController? is unused" warning
TL;DR
popViewController(animated:)
returns UIViewController?
, and the compiler is giving that warning since you aren't capturing the value. The solution is to assign it to an underscore:
_ = navigationController?.popViewController(animated: true)
Swift 3 Change
Before Swift 3, all methods had a "discardable result" by default. No warning would occur when you did not capture what the method returned.
In order to tell the compiler that the result should be captured, you had to add @warn_unused_result
before the method declaration. It would be used for methods that have a mutable form (ex. sort
and sortInPlace
). You would add @warn_unused_result(mutable_variant="mutableMethodHere")
to tell the compiler of it.
However, with Swift 3, the behavior is flipped. All methods now warn that the return value is not captured. If you want to tell the compiler that the warning isn't necessary, you add @discardableResult
before the method declaration.
If you don't want to use the return value, you have to explicitly tell the compiler by assigning it to an underscore:
_ = someMethodThatReturnsSomething()
Motivation for adding this to Swift 3:
- Prevention of possible bugs (ex. using
sort
thinking it modifies the collection) - Explicit intent of not capturing or needing to capture the result for other collaborators
The UIKit API appears to be behind on this, not adding @discardableResult
for the perfectly normal (if not more common) use of popViewController(animated:)
without capturing the return value.
Read More
- SE-0047 Swift Evolution Proposal
- Accepted proposal with revisions
When life gives you lemons, make an extension:
import UIKit
extension UINavigationController {
func pop(animated: Bool) {
_ = self.popViewController(animated: animated)
}
func popToRoot(animated: Bool) {
_ = self.popToRootViewController(animated: animated)
}
}
Note that adding something like @discardableResult func pop(animated: Bool) -> UIViewController?
will result in the same warning you are trying to avoid.
With the extension you can now write:
func exitViewController()
{
navigationController?.pop(animated: true)
}
func popToTheRootOfNav() {
navigationController?.popToRoot(animated: true)
}
Edit: Added popToRoot too.