如何为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:
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—
btcPriceis 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

