As an iOS Developer, you’ve likely encountered that annoying yellow warning in Xcode that says: “Result of call to function returning ‘Type’ is unused”. In Swift programming, the compiler is strictly safe by design; if a function returns a value, Swift expects you to do something with it. However, there are times when that return value is an optional “extra” and not the primary purpose of the function call.
How do we tell Xcode that it’s okay to ignore that value without cluttering our code with useless assignments like let _ = myFunction()? This is where the @discardableResult in Swift attribute comes into play.
In this comprehensive tutorial, you will learn exactly what it is, how to implement it, and the best practices for using it when developing applications with Swift and SwiftUI for iOS, macOS, and watchOS.
1. What is @discardableResult in Swift?
In older versions of Swift (before Swift 3), the return values of functions could be ignored by default. If you wanted to force the developer to use the result, you had to add an attribute called @warn_unused_result.
Apple reversed this behavior because ignoring results often led to severe logical bugs (for example, calling a method that returns a modified string but doesn’t mutate the original one, and failing to save the result). Today, in modern Swift programming, the default behavior demands that you use the return value.
The @discardableResult attribute is simply a modifier that you place right before a function or method declaration. Its sole purpose is to tell the Swift compiler: “Hey, this function returns a value, but it is completely safe and acceptable if the developer decides to ignore it”.
The Problem: Warnings in Xcode
Imagine you have a class that manages a local database. You have a deleteUser function that removes the record and returns a boolean indicating whether the operation was successful.
class DatabaseManager {
func deleteUser(id: Int) -> Bool {
// Deletion logic...
print("User \(id) deleted")
return true
}
}
let db = DatabaseManager()
db.deleteUser(id: 42)
If you write this in Xcode, you will immediately see a warning on the line where you call the function.
Ignoring warnings in Xcode is a bad practice for any iOS Developer, as it hides potential real problems under a sea of yellow alerts.
2. How and When to Use @discardableResult in Swift
The solution to the problem above is extremely simple. You just need to add the attribute before the func keyword:
class DatabaseManager {
@discardableResult
func deleteUser(id: Int) -> Bool {
// Deletion logic...
print("User \(id) deleted")
return true
}
}
let db = DatabaseManager()
db.deleteUser(id: 42) // Zero warnings in Xcode!
But the real question isn’t how to use it (it’s just one word), but when it’s architecturally correct to use it. Let’s look at the most professional use cases.
2.1. Mutating Functions that Return the Old Object
It is very common in Swift programming to have functions that alter a collection or a state and, for convenience, return the value that was just overwritten or removed.
struct NavigationStack {
private var views: [String] = []
mutating func push(_ view: String) {
views.append(view)
}
@discardableResult
mutating func pop() -> String? {
return views.popLast()
}
}
Sometimes, when popping a view in iOS or macOS, you need to know which view was removed to log it in an analytics system. Other times, you simply want to go back and don’t care about the removed value. @discardableResult allows both uses cleanly.
2.2. The Builder Pattern
This is the star use case for @discardableResult in Swift. The Builder pattern is used to construct complex objects step by step. It became very popular in UIKit and remains highly useful in logic layer architectures, even if you use SwiftUI for the view.
class URLRequestBuilder {
private var url: String = ""
private var method: String = "GET"
private var headers: [String: String] = [:]
init(baseURL: String) {
self.url = baseURL
}
@discardableResult
func setMethod(_ method: String) -> URLRequestBuilder {
self.method = method
return self
}
@discardableResult
func addHeader(key: String, value: String) -> URLRequestBuilder {
self.headers[key] = value
return self
}
func build() -> URLRequest? {
// Builds and returns the final request
guard let validURL = URL(string: url) else { return nil }
var request = URLRequest(url: validURL)
request.httpMethod = self.method
request.allHTTPHeaderFields = self.headers
return request
}
}
Because we return self and use @discardableResult, an iOS Developer can use this class by chaining methods fluidly:
// Chained usage (Fluent Interface)
let request = URLRequestBuilder(baseURL: "https://api.example.com")
.setMethod("POST")
.addHeader(key: "Auth", value: "Bearer Token")
.build()
If we didn’t use @discardableResult, the compiler would complain at each step of the chain or if we decided to configure the builder line by line without chaining.
3. Applying @discardableResult in the Apple Ecosystem (iOS, macOS, watchOS)
One of the great advantages of Swift is that the business logic is identical across all platforms. Using @discardableResult will help you create frameworks and packages (Swift Packages) that are pleasant to consume regardless of the target device.
3.1. In SwiftUI: State Managers and ViewModels
Although SwiftUI is declarative and uses view modifiers that already implement similar concepts, in the layer of your ObservableObject or domain models, the use of this attribute is crucial.
Imagine a ViewModel for an Apple Watch app (watchOS) that tracks workouts:
import SwiftUI
class WorkoutViewModel: ObservableObject {
@Published var caloriesBurned: Double = 0.0
@discardableResult
func addActivity(minutes: Double, intensity: Double) -> Double {
let addedCalories = minutes * intensity * 5.0
self.caloriesBurned += addedCalories
return addedCalories
}
}
In your SwiftUI view, you might have a button that simply calls the function regardless of the internal calculations for that specific session:
struct WorkoutView: View {
@StateObject var viewModel = WorkoutViewModel()
var body: some View {
VStack {
Text("Calories: \(viewModel.caloriesBurned)")
Button("Workout for 10 min") {
// We don't care about the returned value here, we just want the total to update
viewModel.addActivity(minutes: 10, intensity: 1.2)
}
}
}
}
If a developer later needs to use the return value to show an animation like “You burned X calories!”, the function is already prepared to return the value without rewriting any code.
3.2. CoreData and Database Operations (iOS & macOS)
In heavy macOS or iOS applications, it is common to have save-to-disk functions.
class DataStore {
@discardableResult
func saveContext() -> Error? {
do {
try context.save()
return nil // No errors
} catch {
return error
}
}
}
In critical flows, you will check the returned error. In background auto-saves when closing the app, you might simply call saveContext() without assigning its result.
4. Best Practices: When NOT to use @discardableResult
As with any powerful tool in Xcode, it can be abused. A good iOS Developer knows when not to use it.
- Do not use it to hide bad architecture: If your main function is to calculate something and it has no side effects, the return value should NEVER be discardable. For example, an
add(a: Int, b: Int) -> Intfunction makes no sense with@discardableResult. If you ignore the result, the function call was a waste of CPU. - Critical Alerts: If the function returns a status code or an error that is critical to data integrity, force the developer to handle it. Do not add the attribute; let Xcode yell at them if they don’t process a potential payment gateway error, for instance.
- Pure Functions: If the method does not mutate the object’s internal state, using
@discardableResultis an anti-pattern.
5. Conclusion
Mastering compiler attributes like @discardableResult in Swift is what separates a novice programmer from a true Senior iOS Developer. It allows you to design APIs and classes that are flexible, clean, and expressive, without compromising the safety that Swift programming guarantees us.
When developing for the Apple ecosystem, whether it’s a complex window management app on macOS, a fluid SwiftUI interface for iOS, or a lightweight app for watchOS, correctly utilizing compiler directives in Xcode will keep your codebase free of warnings and your mind focused on creating great user experiences.
If you have any questions about this article, please contact me and I will be happy to help you . You can contact me on my X profile or on my Instagram profile.