You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过回调传递网络类错误至ViewController?解决类型不兼容编译错误

Fixing the 'Nil is incompatible with expected argument type UserDetail' Error

Hey there! Let's get this sorted out quickly. The error you're hitting happens because your completion closure's first parameter is defined as a non-optional UserDetail type, but you're trying to pass nil when an error occurs (since there's no valid user data to return in that case).

Here are two solid solutions to fix this:

1. Make the Completion's First Parameter Optional

The simplest fix is to update your network function's completion closure to accept an optional UserDetail? instead of the non-optional UserDetail. This lets you pass nil when there's an error, and a valid UserDetail instance when the request/parsing succeeds.

Before (Error-Prone Code):

func fetchUserDetail(completion: @escaping (UserDetail, Error?) -> Void) {
    // Your API request and parsing logic here
    if let parsingError = parsingError {
        completion(nil, parsingError) // ❌ Compiler error here
        return
    }
    completion(decodedUser, nil)
}

After (Fixed Code):

func fetchUserDetail(completion: @escaping (UserDetail?, Error?) -> Void) {
    // Your API request and parsing logic here
    if let parsingError = parsingError {
        completion(nil, parsingError) // ✅ No more error
        return
    }
    completion(decodedUser, nil)
}

In your ViewController, you'll then check if the user detail exists before using it:

networkManager.fetchUserDetail { user, error in
    if let error = error {
        // Handle the error (show alert, log, etc.)
        print("Failed to fetch user: \(error.localizedDescription)")
        return
    }
    
    guard let user = user else {
        // Edge case: no error but no user data (handle if needed)
        return
    }
    
    // Use the user data to update your UI
    self.updateUI(with: user)
}

For cleaner, more readable code (and to avoid ambiguous optional parameters), use Swift's built-in Result type. It's designed explicitly for success/failure scenarios like this.

Step 1: Update the Network Function

// Define a custom error enum for better error handling (optional but highly recommended)
enum NetworkError: Error {
    case invalidURL
    case requestFailed(statusCode: Int)
    case parsingFailed
}

func fetchUserDetail(completion: @escaping (Result<UserDetail, NetworkError>) -> Void) {
    guard let url = URL(string: "your-api-url-here") else {
        completion(.failure(.invalidURL))
        return
    }
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            // Wrap system error if needed, or return your custom error
            completion(.failure(.requestFailed(statusCode: (response as? HTTPURLResponse)?.statusCode ?? 0)))
            return
        }
        
        guard let data = data else {
            completion(.failure(.requestFailed(statusCode: 0)))
            return
        }
        
        do {
            let decodedUser = try JSONDecoder().decode(UserDetail.self, from: data)
            completion(.success(decodedUser))
        } catch {
            completion(.failure(.parsingFailed))
        }
    }.resume()
}

Step 2: Handle the Result in ViewController

networkManager.fetchUserDetail { result in
    DispatchQueue.main.async { // Always update UI on main thread!
        switch result {
        case .success(let user):
            self.updateUI(with: user)
        case .failure(let error):
            switch error {
            case .invalidURL:
                self.showAlert(title: "Error", message: "Invalid API URL")
            case .requestFailed(let statusCode):
                self.showAlert(title: "Request Failed", message: "Status code: \(statusCode)")
            case .parsingFailed:
                self.showAlert(title: "Error", message: "Failed to parse user data")
            }
        }
    }
}

This approach makes your code more expressive—anyone reading it immediately knows that the closure will return either a successful UserDetail or a specific error type, no guesswork required.


内容的提问来源于stack exchange,提问作者Xcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:13:03