我搜索了此主题,但找不到解决问题的方法。这是我的loadData函数可以从JSON对象获取数据
@IBOutlet weak var collectionVitrin: UICollectionView!
var vitrinDecodePost = [VitrinDecode]() // Decodable
func loadDatas(limit : Int) {
guard let url = URL(string: "my Url") else { return }
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
let paramString = "limit=\(limit)"
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest) {
(data, response, error) in
guard let _:NSData = data as NSData? , let _:URLResponse = response, error == nil else {
print("Mistake")
return
}
guard let data = data else { return }
do {
let abc = try JSONDecoder().decode([VitrinDecode].self, from: data)
self.vitrinDecodePost = abc
DispatchQueue.main.async {
self.collectionVitrin.reloadData()
}
} catch { print(error)}
}
task.resume()
}
我在ViewDidLoad中运行此功能:
var deger : Int = 10
override func viewDidLoad() {
super.viewDidLoad()
loadData(limit: deger)
}
滚动结束后,我想添加更多数据,所以我添加了willDisplay函数
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return self.vitrinDecodePost.count
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
let lastindex = self.vitrinDecodePost.count - 1
if indexPath.row == lastindex{
loadDatas(limit: 20)
self.collectionVitrin.reloadData()
}
}
页面加载后,我的单元格中显示10个项目,但是到达页面末尾(最后一个索引)时,collectionview不显示任何内容。它必须在我的collectionview单元格中显示20个项目。我忘记了什么?
答案 0 :(得分:1)
您应该删除self.collectionVitrin.reloadData()
函数中LoadDatas(limit: 20)
之后调用的willDisplay
。
但是,如果我可以建议您在collectionview上实现无限滚动,那么我会做一些改变。
首先,我建议您更改api调用。 您应该限制每个api调用发回的元素数量的限制,但也应实现偏移量变量。这样效率更高。
在您的情况下,您的第二个api调用只是再次请求相同的对象,但请求中的限制更大。您基本上每次都要求相同的数据。 添加偏移量可使您每次仅请求新数据。该偏移量应该是您已经拥有的数据量。
第二,当您到达数据末尾或已经在请求数据时,应该尝试添加故障保护机制。否则,如果您到达集合视图的底部,最终将导致呼叫循环。这是我根据您的代码实现无限加载的方法
@IBOutlet weak var collectionVitrin: UICollectionView!
var limitPerCall: Int = 10
var isLoadindNewData = false
var shouldLoadMoreData = true
var vitrinDecodePost = [VitrinDecode]() // Decodable
func loadDatas(limit : Int, offset: Int) {
guard let url = URL(string: "my Url") else { return }
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
let parameters = ["limit": "\(limit)", "offset": "\(offset)"] as Dictionary<String, String>
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else { return }
request.httpBody = httpBody
let task = session.dataTask(with: request as URLRequest) { [weak self]
(data, response, error) in
guard let strongSelf = self, let _:NSData = data as NSData? , let _:URLResponse = response, error == nil else {
print("Mistake")
return
}
/// No More data to gather stop making api calls
guard let data = data else {
strongSelf.shouldLoadMoreData = false
return
}
do {
let abc = try JSONDecoder().decode([VitrinDecode].self, from: data)
strongSelf.vitrinDecodePost.append(contentsOf: abc)
//// Reload the new data and and indicates that api call can be
made again
DispatchQueue.main.async {
strongSelf.isLoadingNewData = false
strongSelf.collectionVitrin.reloadData()
}
} catch { print(error)}
}
task.resume()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection
section: Int) -> Int {
return self.vitrinDecodePost.count
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell:
UICollectionViewCell, forItemAt indexPath: IndexPath) {
let lastindex = self.vitrinDecodePost.count - 1
if indexPath.row == lastindex && !isLoadindNewData && shouldLoadMoreData {
/// Forbids multiple api calls to happen at the same time
isLoadindNewData = true
loadDatas(limit: limitPerCall, offset: vitrinDecodePost.count)
}
}
希望有帮助。
最佳