SwiftUI中如何向类传递类型?解决Query类data属性类型报错问题
解决方案
你遇到的问题核心是:type是实例属性,不能直接用作类型标注。正确的做法是把Query改成泛型类,利用Swift泛型绑定数据类型,具体修改如下:
修改后的Query类代码
import Foundation import Combine class Query<T: Decodable>: ObservableObject { let url: String init(url: String) { self.url = "https://api.domain.com" + url // 初始化时自动触发请求,也可以留到外部手动调用 fetchData() } @Published var data: T? @Published var error: Error? @Published var hasError: Bool = false @Published var isSuccess: Bool = false @Published var isLoading: Bool = false @Published var isFetching: Bool = false private var bag = Set<AnyCancellable>() func fetchData() { isLoading = true isFetching = true guard let url = URL(string: self.url) else { error = NSError(domain: "Invalid URL", code: -1, userInfo: nil) hasError = true isLoading = false isFetching = false return } URLSession.shared.dataTaskPublisher(for: url) .receive(on: DispatchQueue.main) .tryMap { data, response in guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw NSError(domain: "Request failed", code: (response as? HTTPURLResponse)?.statusCode ?? -2, userInfo: nil) } return data } .decode(type: T.self, decoder: JSONDecoder()) .sink(receiveCompletion: { [weak self] completion in guard let self = self else { return } self.isLoading = false self.isFetching = false switch completion { case .finished: self.isSuccess = true case .failure(let err): self.error = err self.hasError = true self.isSuccess = false } }, receiveValue: { [weak self] decodedData in self?.data = decodedData }) .store(in: &bag) } }
修改View的使用方式
现在不需要传入type参数,直接通过泛型<Post>指定数据类型:
import SwiftUI struct AView: View { @StateObject var query = Query<Post>(url: "/post/id") var body: some View { if query.isSuccess, let post = query.data { Text(post.title) } else if query.isLoading { ProgressView() } else if query.hasError { Text("加载失败:\(query.error?.localizedDescription ?? "未知错误")") } } } // 示例Post模型(需符合Decodable协议) struct Post: Decodable { let title: String // 其他业务属性... }
关键说明
- 泛型
<T: Decodable>让Query类适配任意符合Decodable的模型类型,无需单独传递类型参数。 - 解码时直接使用
T.self,编译器会自动根据泛型参数推断具体模型类型。 - View中通过
Query<Post>明确类型后,query.data会自动成为Post?类型,无需额外类型转换。
内容的提问来源于stack exchange,提问作者drrefe
相关产品推荐
相关产品推荐

