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

iOS Swift应用网络请求异步问题:为何先输出‘I'm here’再返回JSON?

Why You're Seeing "I'm here before JSON" & How to Fix It

Hey there! Let's break down exactly why your output is out of order, and walk through the best ways to fix it in Swift.

The Root Cause: Asynchronous Network Calls

Nearly all network requests in iOS (like using URLSession) run asynchronously. That means when you call dataTask.resume(), the system kicks off the network work on a background thread—it doesn't pause your main thread to wait for the response to come back.

Your code keeps executing line-by-line on the main thread, so the print("I'm here before JSON") runs immediately, while the network request chugs along in the background. Only once the request finishes (success or failure) does the closure/handler you passed to dataTask get executed.

Here's what your code probably looks like right now, to illustrate:

func getWebsiteContent() {
    let url = URL(string: "https://your-target-site.com")!
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        // This code runs LATER, when the network call finishes
        if let data = data {
            print("Parsed JSON successfully!")
        }
    }
    task.resume()
    // This code runs RIGHT AWAY, before the network call finishes
    print("I'm here before JSON")
}

How to Fix It: Handle Asynchronous Code Properly

You need to ensure any code that depends on the network response only runs after the response is received. There are two modern, recommended ways to do this in Swift:

1. Use Completion Handlers (Older but Still Widely Used)

Wrap your network logic in a function that takes a completion closure—this lets you pass in the code you want to run once the request finishes.

// Define the fetch function with a completion handler
func fetchWebsiteContent(completion: @escaping (Result<Data, Error>) -> Void) {
    guard let url = URL(string: "https://your-target-site.com") else {
        completion(.failure(NSError(domain: "InvalidURL", code: 0, userInfo: nil)))
        return
    }
    
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            completion(.failure(error))
            return
        }
        
        guard let responseData = data else {
            completion(.failure(NSError(domain: "NoData", code: 0, userInfo: nil)))
            return
        }
        
        completion(.success(responseData))
    }
    task.resume()
}

// Call the function and handle the result
fetchWebsiteContent { result in
    switch result {
    case .success(let data):
        // Parse your JSON or process the data HERE
        print("Got JSON response!")
        // If you need to update UI, switch back to the main thread:
        DispatchQueue.main.async {
            // Update labels, tables, etc.
        }
    case .failure(let error):
        print("Request failed: \(error.localizedDescription)")
    }
}

// Any code here still runs before the network call finishes, and that's okay!

2. Use Async/Await (Swift 5.5+, iOS 15+)

This is the cleaner, more modern approach that eliminates "callback hell" by letting you write asynchronous code that reads like synchronous code.

// Define an async throwing function for the network call
func fetchWebsiteContent() async throws -> Data {
    guard let url = URL(string: "https://your-target-site.com") else {
        throw NSError(domain: "InvalidURL", code: 0, userInfo: nil)
    }
    // `data(from:)` is an async method that waits for the response
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

// Call the function from an async context (like a Task)
Task {
    do {
        let data = try await fetchWebsiteContent()
        // Parse JSON or process data HERE
        print("Got JSON response!")
        // Update UI safely using MainActor
        await MainActor.run {
            // Update your UI elements here
        }
    } catch {
        print("Request failed: \(error.localizedDescription)")
    }
}

Key Takeaway

Never assume asynchronous operations (like network calls) will finish before the next line of code runs. Always use completion handlers or async/await to chain your logic so that code dependent on the response runs only after the response is available.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:14:51