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

URLSession dataTask返回nil且未进入回调代码块的问题求助

Swift URLSession dataTask 未触发回调问题

我的URL在浏览器中可正常访问,但Swift代码里的let task = URLSession.shared.dataTask(with: url) { data, response, error in这一行,回调完全没触发——在dataTask行打断点时,程序直接跳到task.resume(),回调里的响应、错误、数据处理逻辑都没执行。

调用代码

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    switch indexPath.section {
    case 0:
        let selectedCategory = recipes[indexPath.row]
        let destVC = RecipeResultsVC(category: selectedCategory.tag)
        navigationController?.pushViewController(destVC, animated: true)

    case 1:
        let selectedRecipe = similarRecipesArray[indexPath.row]
        print("Selected Recipe ID: \(selectedRecipe.id)")

        fetchRecommendedRecipeInstructions(recipeID: String(selectedRecipe.id))
        // Download and set the full-screen background image
        recipeResultsVC.recipeImage.downloadImage(fromURL: recommendedRecipeInstructions[0].image)
        recipeResultsVC.setBackgroundImage()
    default:
        break
    }
}

func fetchRecommendedRecipeInstructions(recipeID: String) {
    print("Fetching recipe instructions for recipeID: \(recipeID)")
    NetworkManager.shared.getRecommendedRecipeInstructions(recipeID: recipeID) { [weak self] result in
        print("Before guard: \(self)")
        guard let self = self else { return }
        print("After guard: \(self)")
        switch result {
        case .success(let instructions):
            print("Fetched Instructions are : \(instructions)")
            //self.recommendedRecipeInstructions.append(contentsOf: instructions)
        case .failure(let error):
            print("Error fetching instructions: \(error.localizedDescription)")
        }
    }
}

网络请求代码

func getRecommendedRecipeInstructions(recipeID: String, completion: @escaping (Result<Instructions, SPError>) -> Void) {
    
    let urlString = "https://api.spoonacular.com/recipes/\(recipeID)/information?apiKey=\(Api.apiKey)"
    
    guard let url = URL(string: urlString) else {
        completion(.failure(.invalidQuery))
        return
    }
    
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            print("Error fetching data: \(error)")
            completion(.failure(.invalidResponse))
            return
        }
        
        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
            completion(.failure(.invalidResponse))
            return
        }
        
        guard let data = data else {
            completion(.failure(.invalidData))
            return
        }
        
        do {
            let decoder = JSONDecoder()
            let recipeInstructions = try decoder.decode(Instructions.self, from: data)
            completion(.success(recipeInstructions))
        } catch {
            completion(.failure(.invalidData))
        }
    }
    task.resume()
}

排查与解决建议

1. 修复ViewController提前释放问题

从调用代码看,fetchRecommendedRecipeInstructions是异步请求,回调里用了[weak self],如果当前ViewController在请求完成前被释放(比如被pop或销毁),guard let self = self会直接return,导致看不到任何回调日志。另外,请求未完成就直接操作recommendedRecipeInstructions[0],会引发数组越界或空值问题。

修改方案:
把UI更新逻辑移到请求成功的回调内,确保数据返回后再操作:

case .success(let instructions):
    print("Fetched Instructions are : \(instructions)")
    self.recommendedRecipeInstructions = instructions // 根据实际情况调整赋值逻辑
    self.recipeResultsVC.recipeImage.downloadImage(fromURL: self.recommendedRecipeInstructions[0].image)
    self.recipeResultsVC.setBackgroundImage()

2. 增加日志定位问题

在网络请求代码的URL创建成功后添加打印,确认URL和浏览器完全一致:

guard let url = URL(string: urlString) else {
    completion(.failure(.invalidQuery))
    return
}
print("Request URL: \(url)") // 新增日志

同时在dataTask回调开头加打印,确认是否真的进入回调:

let task = URLSession.shared.dataTask(with: url) { data, response, error in
    print("Entered dataTask callback") // 新增日志
    // 原有逻辑...
}

3. 修正错误处理逻辑

原代码把网络错误也归类为.invalidResponse,无法区分具体错误类型,建议修改错误枚举,增加网络错误的关联值:

// 假设SPError定义如下
enum SPError: Error {
    case invalidQuery
    case invalidResponse
    case invalidData
    case networkError(Error) // 新增网络错误类型
}

// 网络请求中修改错误处理
if let error = error {
    print("Error fetching data: \(error)")
    completion(.failure(.networkError(error)))
    return
}

4. 检查ATS设置

虽然使用了HTTPS URL,仍需确认App的ATS设置是否允许该域名访问。可临时在Info.plist中添加如下配置测试(仅用于排查,上线前需调整合规):

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:23:23