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
相关产品推荐
相关产品推荐

