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

如何为viewDidLoad添加完成处理程序,使btcprice返回double类型btc值而非nil

Got it, let's tackle this problem step by step. You want to make sure your btcprice function doesn't return nil, and that in viewDidLoad you end up with a valid Double value for the BTC price instead of nil. Here's how to do it properly:

How to Add Completion Handler & Ensure Non-Nil Double for BTC Price

1. Refactor the btcprice Function with Completion Handler (Prevent Nil)

First, let's rework your price-fetching function to use a completion handler that explicitly returns either a valid Double or an error—so you never get stuck with a nil value. Here's a practical implementation:

func fetchBTCPrice(completion: @escaping (Result<Double, Error>) -> Void) {
    // Replace with your actual API endpoint
    guard let url = URL(string: "https://api.yourbtcprovider.com/price") else {
        completion(.failure(NSError(domain: "BTCPriceError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])))
        return
    }
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        // Handle network errors first
        if let error = error {
            completion(.failure(error))
            return
        }
        
        // Guard against empty data
        guard let data = data else {
            completion(.failure(NSError(domain: "BTCPriceError", code: 0, userInfo: [NSLocalizedDescriptionKey: "No data received from server"])))
            return
        }
        
        do {
            // Parse the JSON (adjust this to match your API's response structure)
            let responseJSON = try JSONSerialization.jsonObject(with: data) as? [String: Any]
            guard let rawPrice = responseJSON?["btc_price"] as? Double else {
                // Option 1: Return a default value if parsing fails (e.g., 0.0)
                completion(.success(0.0))
                // Option 2: Return an error to handle failure explicitly
                // completion(.failure(NSError(domain: "BTCPriceError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to parse price as Double"])))
                return
            }
            completion(.success(rawPrice))
        } catch {
            completion(.failure(error))
        }
    }.resume()
}

Key details here:

  • We use Result<Double, Error> to force handling of both success and failure cases
  • Every possible nil scenario (invalid URL, network error, empty data, parsing failure) is accounted for
  • You can choose between returning a safe default value or throwing an error—pick what fits your app's needs

2. Add Completion Logic in viewDidLoad to Guarantee Non-Nil Double

Now in your viewDidLoad, call this function and handle the result to ensure you always have a valid Double to work with:

override func viewDidLoad() {
    super.viewDidLoad()
    
    fetchBTCPrice { [weak self] result in
        // Always update UI on the main thread
        DispatchQueue.main.async {
            switch result {
            case .success(let btcPrice):
                // btcPrice is 100% a non-nil Double here
                self?.updateUIBTCPrice(btcPrice)
                print("Current BTC price: $\(btcPrice)")
            case .failure(let error):
                // Handle the error gracefully (show alert, log, etc.)
                print("Error fetching BTC price: \(error.localizedDescription)")
                // Fallback to a default value if needed
                self?.updateUIBTCPrice(0.0)
            }
        }
    }
}

// Helper to update your UI with the price
private func updateUIBTCPrice(_ price: Double) {
    // Example: Update a label with formatted price
    // btcPriceLabel.text = String(format: "$%.2f", price)
}

Important notes for viewDidLoad:

  • Use [weak self] to avoid retain cycles between the completion handler and your view controller
  • Network calls run in the background, so always dispatch UI updates to the main thread
  • In the success case, you don't need optional binding—btcPrice is guaranteed to be a valid Double
  • In failure cases, you can either show an error message to the user or fall back to a default value, so you never end up with nil

Bonus: Avoid Synchronous Calls (Unless Absolutely Necessary)

If you ever think you need a synchronous version of this function (e.g., for testing), you can use a semaphore—but this is not recommended for production since it blocks the main thread:

func fetchBTCPriceSync() -> Double {
    let semaphore = DispatchSemaphore(value: 0)
    var finalPrice: Double = 0.0
    
    fetchBTCPrice { result in
        switch result {
        case .success(let price):
            finalPrice = price
        case .failure:
            finalPrice = 0.0
        }
        semaphore.signal()
    }
    
    semaphore.wait()
    return finalPrice
}

Stick with async completion handlers for production apps to keep your UI responsive.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:32:41