Swift - 分页时添加加载单元
Swift -Add loading cell while paginating
现在我使用这个问题底部的代码进行分页,一切正常,但我想在分页开始后向 collectionView 添加一个加载单元,并在分页停止后将其删除。
我尝试了以下方法,但它只是将加载单元添加到 cv 的底部并且加载单元永远不会离开。
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datasource.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == tableData.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loadingCell, for: indexPath) as! LoadingCell
cell.spinner.startAnimating()
return cell
}
return cell // this is a normal cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item == tableData.count {
return CGSize(width: collectionView.frame.width, height: 40) // loading cell is 40 pts
}
return CGSize(width: width, height: 80) // normal cell is 80 pts
}
我也试过使用sections但是出现了同样的问题
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return datasource.count
} else {
return 1
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loadingCell, for: indexPath) as! LoadingCell
cell.spinner.startAnimating()
return cell
}
return cell // this is a normal cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.section == 1 {
return CGSize(width: collectionView.frame.width, height: 40) // loading cell is 40 pts
}
return CGSize(width: width, height: 80) // normal cell is 80 pts
}
如何仅在 handlePaginating() 为 called/finished 时删除添加和删除加载单元?
var startKey: String?
override func viewDidLoad() {
super.viewDidLoad()
handlePagination()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let contentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maximumOffset - contentOffset <= 10 {
handlePagination()
}
}
func handlePagination() {
if startKey == nil {
Database...Ref?.queryOrderedByKey().queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// append child to datasource
}
self?.startKey = children.key
})
} else {
Database...Ref?.queryOrderedByKey().queryEnding(atValue: startKey!).queryLimited(toLast: 11).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// insert child in datasource at statIndex
}
self?.startKey = children.key
})
}
}
您必须在当前代码中添加一个额外的标志变量才能正常工作。当前代码中发生的事情是,当最后一个要显示的单元格将调用 handlePagination
时,然后您添加加载单元格,而没有任何条件表明 handlePagination
当前正在处理中。所以在你添加加载单元之后,willDisplay
方法再次调用 api。
希望对您有所帮助。
例如:
var isApiCalling = false
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
let lastElement = tableData.count - 1
if indexPath.item == lastElement && !isApiCalling {
isApiCalling = true
handlePagination()
}
}
func handlePagination() {
//After you get response from API called. reset isApiCalling to false.
isApiCalling = false.
}
我将@PratikPrajapati 回答中的标志 属性 的想法与问题的第一部分结合使用。
我声明了一个 属性 并最初将其设置为 var isPaging = false
。然后在 cellForItem
和 sizeForItem
里面,我检查布尔值是 true
还是 false
.
在 handlePagination()
的 else
子句中,我将标志设置为 isPaging = true
,然后调用 collectionView.reloadData()
,以便在重新加载 cv 时,cellForItem
和 sizeForItem
现在将在加载单元内显示微调器并将其高度设置为 40。
最后在 else
子句的回调中,我将标志设置回 false
并再次调用 collectionView.reloadData()
以便更新所有单元格,微调器不再旋转,并且加载单元的大小为 .zero
:
Database...Ref?.queryOrderedByKey() ....
// callback
self?.isPaging = false
// ...
UIView.performWithoutAnimation {
self?.collectionView.reloadData()
}
...
完整代码如下:
var isPaging = false
var startKey: String?
override func viewDidLoad() {
super.viewDidLoad()
handlePagination()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datasource.count + 1 // *** make sure to add the + 1 to this ***
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == tableData.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loadingCell, for: indexPath) as! LoadingCell
if isPaging {
cell.spinner.startAnimating()
} else {
cell.spinner.stopAnimating()
}
return cell
}
return cell // this is a normal cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item == tableData.count {
if isPaging {
return CGSize(width: collectionView.frame.width, height: 40) // if it's true then set the loading cell's size
} else {
return .zero // if it's false then set the loading cell's size to .zero
}
}
return CGSize(width: width, height: 80) // normal cell is 80 pts
}
func handlePagination() {
if startKey == nil {
Database...Ref?.queryOrderedByKey().queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// append child to datasource
}
self?.startKey = children.key
})
} else {
isPaging = true
collectionView.reloadData()
// add a function to auto scroll to the last cell
Database...Ref?.queryOrderedByKey().queryEnding(atValue: startKey!).queryLimited(toLast: 11).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
self?.isPaging = false
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// insert child in datasource at statIndex
}
self?.startKey = children.key
UIView.performWithoutAnimation {
self?.collectionView.reloadData()
}
})
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let contentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maximumOffset - contentOffset <= 10 {
handlePagination()
}
}
现在我使用这个问题底部的代码进行分页,一切正常,但我想在分页开始后向 collectionView 添加一个加载单元,并在分页停止后将其删除。
我尝试了以下方法,但它只是将加载单元添加到 cv 的底部并且加载单元永远不会离开。
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datasource.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == tableData.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loadingCell, for: indexPath) as! LoadingCell
cell.spinner.startAnimating()
return cell
}
return cell // this is a normal cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item == tableData.count {
return CGSize(width: collectionView.frame.width, height: 40) // loading cell is 40 pts
}
return CGSize(width: width, height: 80) // normal cell is 80 pts
}
我也试过使用sections但是出现了同样的问题
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return datasource.count
} else {
return 1
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loadingCell, for: indexPath) as! LoadingCell
cell.spinner.startAnimating()
return cell
}
return cell // this is a normal cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.section == 1 {
return CGSize(width: collectionView.frame.width, height: 40) // loading cell is 40 pts
}
return CGSize(width: width, height: 80) // normal cell is 80 pts
}
如何仅在 handlePaginating() 为 called/finished 时删除添加和删除加载单元?
var startKey: String?
override func viewDidLoad() {
super.viewDidLoad()
handlePagination()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let contentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maximumOffset - contentOffset <= 10 {
handlePagination()
}
}
func handlePagination() {
if startKey == nil {
Database...Ref?.queryOrderedByKey().queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// append child to datasource
}
self?.startKey = children.key
})
} else {
Database...Ref?.queryOrderedByKey().queryEnding(atValue: startKey!).queryLimited(toLast: 11).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// insert child in datasource at statIndex
}
self?.startKey = children.key
})
}
}
您必须在当前代码中添加一个额外的标志变量才能正常工作。当前代码中发生的事情是,当最后一个要显示的单元格将调用 handlePagination
时,然后您添加加载单元格,而没有任何条件表明 handlePagination
当前正在处理中。所以在你添加加载单元之后,willDisplay
方法再次调用 api。
希望对您有所帮助。
例如:
var isApiCalling = false
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
let lastElement = tableData.count - 1
if indexPath.item == lastElement && !isApiCalling {
isApiCalling = true
handlePagination()
}
}
func handlePagination() {
//After you get response from API called. reset isApiCalling to false.
isApiCalling = false.
}
我将@PratikPrajapati 回答中的标志 属性 的想法与问题的第一部分结合使用。
我声明了一个 属性 并最初将其设置为 var isPaging = false
。然后在 cellForItem
和 sizeForItem
里面,我检查布尔值是 true
还是 false
.
在 handlePagination()
的 else
子句中,我将标志设置为 isPaging = true
,然后调用 collectionView.reloadData()
,以便在重新加载 cv 时,cellForItem
和 sizeForItem
现在将在加载单元内显示微调器并将其高度设置为 40。
最后在 else
子句的回调中,我将标志设置回 false
并再次调用 collectionView.reloadData()
以便更新所有单元格,微调器不再旋转,并且加载单元的大小为 .zero
:
Database...Ref?.queryOrderedByKey() ....
// callback
self?.isPaging = false
// ...
UIView.performWithoutAnimation {
self?.collectionView.reloadData()
}
...
完整代码如下:
var isPaging = false
var startKey: String?
override func viewDidLoad() {
super.viewDidLoad()
handlePagination()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datasource.count + 1 // *** make sure to add the + 1 to this ***
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == tableData.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loadingCell, for: indexPath) as! LoadingCell
if isPaging {
cell.spinner.startAnimating()
} else {
cell.spinner.stopAnimating()
}
return cell
}
return cell // this is a normal cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item == tableData.count {
if isPaging {
return CGSize(width: collectionView.frame.width, height: 40) // if it's true then set the loading cell's size
} else {
return .zero // if it's false then set the loading cell's size to .zero
}
}
return CGSize(width: width, height: 80) // normal cell is 80 pts
}
func handlePagination() {
if startKey == nil {
Database...Ref?.queryOrderedByKey().queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// append child to datasource
}
self?.startKey = children.key
})
} else {
isPaging = true
collectionView.reloadData()
// add a function to auto scroll to the last cell
Database...Ref?.queryOrderedByKey().queryEnding(atValue: startKey!).queryLimited(toLast: 11).observeSingleEvent(of: .value, with: { [weak self](snapshot) in
self?.isPaging = false
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return}
for child in snapshot.children.allObjects as! [DataSnapshot] {
// insert child in datasource at statIndex
}
self?.startKey = children.key
UIView.performWithoutAnimation {
self?.collectionView.reloadData()
}
})
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let contentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maximumOffset - contentOffset <= 10 {
handlePagination()
}
}