Swift 3 Warning of Unused Result

I have been experimenting with converting projects to Swift 3 syntax using the migration tools in Xcode 8. This has been giving me a lot of warnings of the form “Result of call to someFunction is unused”.

By default in Swift 3 ignoring the return value of a function is now considered a warning. This post is my quick summary of what changed, how to suppress the warning if you need to and a feature which may cause you some confusion.

What Changed in Swift 3

In Swift 2.x you could tell the compiler to warn you when you ignored the return value of a function. You did that by marking the function with @warn_unused_result. For example:

@warn_unused_result func doSomething() -> Bool {
  return true
}

Calling that function without using the result will give a warning:

`Result of call to 'doSomething()' is unused`

You can do something similar for Objective-C code using the attribute((warn_unused_result)) annotation:

- (BOOL)doSomething __attribute__((warn_unused_result)) {
  return YES;
}

This gives the warning:

`Ignoring return value of function declared with warn_unused_result attribute`

Note that by default in Objective-C and Swift 2 the default is not to warn on an unused result. That changed for Swift 3. Ignoring the return value of a Swift function is now by default a warning. This explains why I am seeing a lot of new warnings when I migrate a project to Swift 3 using Xcode 8:

Xcode warnings

Silencing the Warnings - @discardableResult

There are two ways to silence the warning:

  • Override the default when declaring the function using @discardableResult
  • Explicitly discard the return value using _

To override the default when declaring a new function and prevent a warning if you ignore the result add the @discardableResult attribute:

@discardableResult func doSomething() -> Bool {
  return true
}

Note this is now the opposite of Swift 2. We add the annotation when we want to suppress the warning.

To prevent the compiler from flooding us with warnings when importing Objective-C code the @discardableResult attribute is automatically added for all non-void functions that are not marked with the ((warn_unused_result)) attribute.

For situations where you want to suppress the warning and explicitly ignore the result of a function assign it to _:

_ = doSomething()

This looks a bit ugly to me but it does make it explicit that you are choosing to ignore the return value.

Discardable Result Lost After Optional Chaining

As I write this with Xcode 8 beta 3 there is a situation where the discardable result attribute does not work as expected. For example, popping a view controller off the navigation stack:

navigationController?.popViewController(animated: true)

The popViewController(animated: Bool) function returns us the view controller it popped from the stack. This Objective-C API is marked with @discardableResult when imported but it still gives us a warning if we do not use the return value:

`Expression of type 'UIViewController?' is unused`

The problem happens when we are working with an optional value. In this example we use optional chaining as the navigationController property of a view controller can be nil. Unfortunately the discardable result attribute is lost after optional chaining.

This is reported as Swift bug SR-1681 (and was fixed in Xcode 8.3 and Swift 3.1). In the meantime you need to explicitly discard the result to avoid the warning:

_ = navigationController?.popViewController(animated: true)

Further Reading