SyntaxStudy
Sign Up
Swift Implicitly Unwrapped and Result Type
Swift Beginner 1 min read

Implicitly Unwrapped and Result Type

Implicitly unwrapped optionals (String!) act as regular optionals but are automatically unwrapped when used. They are primarily for IBOutlets and other cases where a value is guaranteed after initialization but not available at init time. The Result type represents either a success with an associated value or a failure with an Error. It replaces completion handlers that take (Value?, Error?) pairs. Async/await in Swift 5.5+ largely supersedes Result-based completion handlers for asynchronous code.
Example
import Foundation

// Result type
enum APIError: Error {
    case invalidURL
    case networkError(String)
    case decodingError
}

func fetchUser(id: Int, completion: @escaping (Result<User, APIError>) -> Void) {
    guard let url = URL(string: "https://api.example.com/users/\(id)") else {
        completion(.failure(.invalidURL))
        return
    }

    URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            completion(.failure(.networkError(error.localizedDescription)))
            return
        }
        guard let data = data else {
            completion(.failure(.networkError("No data")))
            return
        }
        guard let user = try? JSONDecoder().decode(User.self, from: data) else {
            completion(.failure(.decodingError))
            return
        }
        completion(.success(user))
    }.resume()
}

// Handling Result
fetchUser(id: 1) { result in
    switch result {
    case .success(let user): print("Got user: \(user)")
    case .failure(let error): print("Error: \(error)")
    }
}

// map / flatMap on Result
let result: Result<String, Error> = .success("42")
let parsed = result.flatMap { str -> Result<Int, Error> in
    guard let n = Int(str) else { return .failure(APIError.decodingError) }
    return .success(n)
}