Swift返回页面后CollectionView Cell数量翻倍问题及解决方法
解决CollectionView返回后Cell数量翻倍的问题
首先得帮你定位问题根源:你遇到的这个情况,几乎可以肯定是每次页面重新出现时,都重复调用了API获取数据,而且没有先清空原有的数据源数组,新数据被追加到了旧数组后面,导致数组长度变成原来的两倍,CollectionView的Cell数量自然也跟着翻倍了。
作为刚接触Swift的开发者,这种问题很常见,下面给你一步步的正确处理方式:
1. 先确保数据源数组的初始化与清空
首先,你的数据源数组(比如叫myCoachData),在调用API之前一定要先清空,避免重复添加数据。比如在postToGetMyCoach()方法开头加上:
myCoachData.removeAll() // 清空旧数据,再加载新数据
2. 控制API调用的时机与防重复请求
- 如果你的API是在
viewDidLoad里调用的,那只会执行一次,不会出现返回后重复调用的情况;但如果是在viewWillAppear或者viewDidAppear里调用的,每次页面显示都会执行,这时候就必须先清空数组再请求。 - 另外,建议加一个加载状态标记,避免网络慢的时候重复触发API请求:
private var isLoading = false func postToGetMyCoach() { guard !isLoading else { return } // 如果正在加载,直接返回,避免重复请求 isLoading = true myCoachData.removeAll() // 清空旧数据 let url = "https://xxxxxxxx.azurewebsites.net/api/myCoach" var param: [String: Any] = [:] // 补全你的请求参数 // 后续的URLSession请求代码... // 请求成功后,记得把isLoading设回false DispatchQueue.main.async { self.isLoading = false self.collectionView.reloadData() } // 请求失败也要把isLoading设回false,避免后续无法再请求 // ... 在请求失败的处理代码里加上 self.isLoading = false }
3. 正确刷新CollectionView
请求到数据后,一定要在主线程调用collectionView.reloadData(),确保UI更新是在主线程执行的,避免出现奇怪的UI渲染问题。
4. 可选:利用ViewController生命周期优化
如果你的页面不需要每次回来都重新获取数据(比如数据不会频繁变化),可以把API调用放在viewDidLoad里,这样只会执行一次;如果需要每次回来都刷新数据,就放在viewWillAppear里,但一定要做好清空数组和防重复请求的处理。
给你一个完整的简化示例参考:
class MyCoachViewController: UIViewController, UICollectionViewDataSource { @IBOutlet weak var collectionView: UICollectionView! private var myCoachData: [YourCoachModel] = [] // 你的数据模型数组 private var isLoading = false override func viewDidLoad() { super.viewDidLoad() collectionView.dataSource = self postToGetMyCoach() // 第一次加载数据 } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 如果需要每次回来都刷新数据,就保留这行;不需要的话可以删掉 postToGetMyCoach() } func postToGetMyCoach() { guard !isLoading else { return } isLoading = true myCoachData.removeAll() guard let url = URL(string: "https://xxxxxxxx.azurewebsites.net/api/myCoach") else { print("URL格式错误") isLoading = false return } var request = URLRequest(url: url) request.httpMethod = "POST" // 配置你的请求参数、headers等... let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in guard let self = self else { return } defer { self.isLoading = false } // 不管成功失败,都重置加载状态 if let error = error { print("请求失败:\(error.localizedDescription)") return } guard let data = data else { print("未获取到数据") return } // 解析数据到你的模型数组 do { self.myCoachData = try JSONDecoder().decode([YourCoachModel].self, from: data) DispatchQueue.main.async { self.collectionView.reloadData() } } catch { print("数据解析失败:\(error.localizedDescription)") } } task.resume() } // CollectionView数据源方法 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return myCoachData.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellID", for: indexPath) as! YourCoachCell let coach = myCoachData[indexPath.item] // 配置Cell的内容 cell.nameLabel.text = coach.name // ...其他UI配置 return cell } }
这样处理之后,不管你多少次跳转到其他页面再回来,数据源数组都会先清空再加载新数据,就不会出现Cell数量翻倍的问题了。
内容的提问来源于stack exchange,提问作者Fido
相关产品推荐
相关产品推荐

