Swift三类编译错误求助:extension作用域、result推断、URLSession无request成员
错误原因&修复方案
核心根因
所有报错均由代码嵌套结构错误引发,不存在Xcode故障:
你将ViewController类、URLSession扩展全部嵌套定义在了Category结构体的大括号内部,导致类型、扩展对外不可见,触发连锁编译错误。
单个错误对应修复
1. extension Declaration is only valid at file scope
Swift要求extension必须定义在文件最外层,不能嵌套在其他类、结构体、枚举内部。你需要把URLSession扩展、ViewController类全部移到Category结构体的大括号外面。
2. Unable to infer type of a closure parameter 'result' in the current context
这是连锁报错:编译器找不到URLSession.request方法的定义,无法推断闭包参数result的类型。修复第一个嵌套问题后该错误自动消失,另外还要修正fetch方法里的笔误:你的属性名为categories,但代码里写了self?.category = category,少了后缀s。
3. Value of type 'URLSession' has no member 'request'
同样是嵌套导致的问题:URLSession扩展定义在Category内部,全局的URLSession类型无法识别这个内部扩展,修复嵌套问题后该错误自动消失。
其他隐含逻辑问题修复
Category结构体不能递归包含[Category]属性,你需要单独定义外层接口响应结构体URLSession.request扩展里生成的NetworkError没有传入闭包,会导致失败场景无回调- 不要使用
try!强制解析JSON,改为正常的do-catch捕获错误 - 目标API返回的根结构外层是
{"categories": [...]},不能直接解析为[Category]类型
修复后完整代码
import UIKit import Foundation enum NetworkError: Error { case badRequest case decodingError } // 单个分类模型 struct Category: Codable { let idCategory: String let strCategoryThumb: String let strCategoryDescription: String } // 接口外层响应结构 struct CategoryResponse: Codable { let categories: [Category] } // ViewController移到外层 class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { struct Constants { static let categoriesurl = URL(string: "https://www.themealdb.com/api/json/v1/1/categories.php") static let filterListurl = URL(string: "https://www.themealdb.com/api/json/v1/1/filter.php?c=Beef") static let mealByIdurl = URL(string: "https://www.themealdb.com/api/json/v1/1/lookup.php?i=52874") } let table: UITableView = { let table = UITableView() table.register(UITableViewCell.self, forCellReuseIdentifier: "cell") return table }() private var categories: [Category] = [] override func viewDidLoad() { super.viewDidLoad() view.addSubview(table) table.delegate = self table.dataSource = self fetch() } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() table.frame = view.bounds } func fetch() { // 解析类型改为外层的CategoryResponse URLSession.shared.request(url: Constants.categoriesurl, returning: CategoryResponse.self) {[weak self] result in switch result { case.success(let response): DispatchQueue.main.async { // 赋值修正为categories属性 self?.categories = response.categories self?.table.reloadData() } case.failure(let error): print(error) } } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return categories.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = table.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = categories[indexPath.row].idCategory return cell } } // URLSession扩展移到外层 extension URLSession { func request<T: Codable>(url: URL?, returning: T.Type, completion: @escaping (Result<T, NetworkError>) -> Void) { guard let url = url else { completion(.failure(.badRequest)) return } let task = dataTask(with: url) { data, _, error in guard let data = data, error == nil else { completion(.failure(.badRequest)) return } do { let result = try JSONDecoder().decode(returning, from: data) completion(.success(result)) } catch { completion(.failure(.decodingError)) } } task.resume() } }
内容的提问来源于stack exchange,提问作者Wens Music
相关产品推荐
相关产品推荐

