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

SwiftUI调用API时出现Unexpected non-void return value错误如何解决?

问题原因
  • 你调用的URLSession.shared.dataTask是异步执行的网络任务,它的尾随闭包返回类型为Void,你在闭包里写return img.string相当于尝试给这个无返回值的闭包返回字符串,自然会报"Unexpected non-void return value in void function"错误
  • 其次异步任务不会阻塞当前函数执行,getFavoriteDoggo在调用.resume()之后就会直接执行结束,根本等不到网络请求返回结果,所以不可能通过同步return的方式拿到URL字符串
解决方案

你确实需要用completion handler来接收异步返回的结果,实现步骤如下:

  1. 改造getFavoriteDoggo函数,移除同步返回值,新增completion回调参数
  2. 网络请求拿到结果后,在主队列调用completion把URL字符串回传
  3. 改造各个犬种对应的获取方法,在completion回调中给对应的@Published属性赋值,不需要再返回值
改造后的完整代码
import Combine
import SwiftyJSON // 保留你原有项目的SwiftyJSON引入

class DoggoViewModel: ObservableObject {
    @Published var mamaluteImg = ""
    @Published var goldenImg = ""
    @Published var samoyedImg = ""
    @Published var chowImg = ""
    @Published var huskyImg = ""

    func getMamalute() {
        getFavoriteDoggo(breed: "malamute") { [weak self] imgUrl in
            guard let self = self, let imgUrl = imgUrl else { return }
            self.mamaluteImg = imgUrl
        }
    }
    
    func getChowChow() {
        getFavoriteDoggo(breed: "chow") { [weak self] imgUrl in
            guard let self = self, let imgUrl = imgUrl else { return }
            self.chowImg = imgUrl
        }
    }
    
    func getHusky() {
        getFavoriteDoggo(breed: "husky") { [weak self] imgUrl in
            guard let self = self, let imgUrl = imgUrl else { return }
            self.huskyImg = imgUrl
        }
    }
    
    func getSamoyed() {
        getFavoriteDoggo(breed: "samoyed") { [weak self] imgUrl in
            guard let self = self, let imgUrl = imgUrl else { return }
            self.samoyedImg = imgUrl
        }
    }
    
    func getGoldenRetriever() {
        getFavoriteDoggo(breed: "retriever/golden") { [weak self] imgUrl in
            guard let self = self, let imgUrl = imgUrl else { return }
            self.goldenImg = imgUrl
        }
    }

    // 新增completion回调,参数为可选的URL字符串
    func getFavoriteDoggo(breed: String, completion: @escaping (String?) -> Void) {
        guard let url = URL(string: "https://dog.ceo/api/breed/\(breed)/images/random") else {
            print("Trouble parsing url")
            completion(nil)
            return
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request){ data, response, error in
            if let error = error {
                print(error.localizedDescription)
                completion(nil)
                return
            }
            
            guard let data = data else {
                completion(nil)
                return
            }
            
            do {
                let response = try JSON(data: data)
                let imgUrl = response["message"].string
                // 切换主队列回调,保证UI更新在主线程执行
                DispatchQueue.main.async {
                    completion(imgUrl)
                }
            } catch {
                print("JSON解析失败: \(error.localizedDescription)")
                DispatchQueue.main.async {
                    completion(nil)
                }
            }
        }.resume()
    }
}
补充说明

如果你的项目最低支持iOS 15/macOS 12及以上版本,也可以用Swift Concurrency的async/await写法,代码会更简洁,不需要嵌套completion回调。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:48:03