Swift中TableView双数据源的正确实现方法求助
问题根源分析
你的代码存在两个核心问题导致TableView无法刷新:
- 错误创建新的ViewController实例:在
CategoryViewController的点击方法中,你新建了一个SearchViewController对象,调用它的fetchCategoryData方法后,数据更新的是这个从未显示的新实例,而非当前界面上正在展示的那个SearchViewController。 - 数据源赋值错误:在
fetchData方法中,你尝试将数组myData直接赋值给tableView.dataSource,但数组并不实现UITableViewDataSource协议,这是无效操作,会导致数据源逻辑混乱。
解决方案及代码修正
1. 修正SearchViewController的数据源实现
让SearchViewController自身实现UITableViewDataSource协议,通过内部数组catsModel管理数据,而非直接给tableView.dataSource赋值数组。
class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var tableView: UITableView! var catsModel: [CatModel] = [] override func viewDidLoad() { super.viewDidLoad() // 初始化时设置数据源和代理为自身 tableView.dataSource = self tableView.delegate = self // 加载全部数据 fetchData() } // 获取全部猫咪图片(修正后) func fetchData() { guard var endPoint = // 你的endpoint配置 else { return } endPoint.queryItems = queryParameters.map({ (key, value) in URLQueryItem(name: key, value: value) }) guard let url = endPoint.url else { return } var request = URLRequest(url: url) request.setValue(ApiClient.Identifiers.apiKey, forHTTPHeaderField: "x-api-key") let task = URLSession.shared.dataTask(with: request) { data, response, error in DispatchQueue.main.async { if let error = error { print(error.debugDescription) return } guard let data = data else { print("未获取到数据") return } do { let myData = try JSONDecoder().decode([CatModel].self, from: data) self.catsModel = myData self.tableView.reloadData() } catch let error { print(error) } } } task.resume() } // 按分类ID筛选数据(修正后) func fetchCategoryData(categoryID: Int) { var endpoint = URLComponents() // 补全你的URL配置(scheme、host、path等) endpoint.queryItems = [URLQueryItem(name: "category_id", value: "\(categoryID)")] guard let url = endpoint.url else { return } var request = URLRequest(url: url) request.setValue(ApiClient.Identifiers.apiKey, forHTTPHeaderField: "x-api-key") let task = URLSession.shared.dataTask(with: request) { data, response, error in DispatchQueue.main.async { if let error = error { print(error.debugDescription) return } guard let data = data else { print("未获取到数据") return } do { let myData = try JSONDecoder().decode([CatModel].self, from: data) self.catsModel = myData self.tableView.reloadData() } catch let error { print(error) } } } task.resume() } // MARK: UITableViewDataSource 实现 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return catsModel.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 替换为你的Cell标识符和自定义Cell类 let cell = tableView.dequeueReusableCell(withIdentifier: "CatCell", for: indexPath) as! CatTableViewCell let cat = catsModel[indexPath.row] // 根据CatModel配置Cell内容(示例) // cell.catNameLabel.text = cat.name // cell.catImageView.kf.setImage(with: URL(string: cat.imageUrl)) return cell } }
2. 修正CategoryViewController的分类点击逻辑
根据你的页面跳转场景,选择以下两种方式之一:
场景A:从CategoryViewController跳转到新的SearchViewController
直接创建实例并传入分类ID后跳转:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let cat = catsModel[indexPath.row] let searchVC = SearchViewController() searchVC.fetchCategoryData(categoryID: cat.id) navigationController?.pushViewController(searchVC, animated: true) }
场景B:SearchViewController已在导航栈中(从Search跳转到Category后返回)
用闭包回调传递分类ID,更新原SearchViewController的数据:
// CategoryViewController中添加闭包属性 class CategoryViewController: UIViewController, UICollectionViewDataSource { var onCategorySelected: ((Int) -> Void)? var catsModel: [CategoryModel] = [] // ...其他代码 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let cat = catsModel[indexPath.row] // 触发回调传递分类ID onCategorySelected?(cat.id) navigationController?.popViewController(animated: true) } } // SearchViewController中跳转到Category时设置闭包 func showCategoryPage() { let categoryVC = CategoryViewController() categoryVC.onCategorySelected = { [weak self] categoryID in self?.fetchCategoryData(categoryID: categoryID) } navigationController?.pushViewController(categoryVC, animated: true) }
额外注意事项
- 确保TableView的Cell标识符与代码中
dequeueReusableCell的标识符完全一致 - 网络请求中避免强制解包
data!,改用guard let做安全判断 - 若使用自定义Cell,需确保Cell类已正确关联XIB或Storyboard
内容的提问来源于stack exchange,提问作者maytime
相关产品推荐
相关产品推荐

