限制tableView中显示的单元格数量,滚动到最后一个单元格时加载更多单元格
Posted
技术标签:
【中文标题】限制tableView中显示的单元格数量,滚动到最后一个单元格时加载更多单元格【英文标题】:Limit the amount of cells shown in tableView, load more cells when scroll to last cell 【发布时间】:2017-12-13 17:05:33 【问题描述】:我正在尝试设置仅显示特定数量的单元格的表格视图。显示该单元格后,用户可以继续滚动以显示更多单元格。截至目前,我正在检索要在 viewDidLoad 中显示的所有 JSON 数据并将它们存储在一个数组中。仅出于示例目的,我首先尝试仅显示 2 个单元格,用户滚动到屏幕底部的一个单元格将出现下一个单元格。到目前为止,这是我的代码:
class DrinkViewController: UIViewController
@IBOutlet weak var drinkTableView: UITableView!
private let networkManager = NetworkManager.sharedManager
fileprivate var totalDrinksArray: [CocktailModel] = []
fileprivate var drinkImage: UIImage?
fileprivate let DRINK_CELL_REUSE_IDENTIFIER = "drinkCell"
fileprivate let DRINK_SEGUE = "detailDrinkSegue"
var drinksPerPage = 2
var loadingData = false
override func viewDidLoad()
super.viewDidLoad()
drinkTableView.delegate = self
drinkTableView.dataSource = self
networkManager.getJSONData(function: urlFunction.search, catagory: urlCatagory.cocktail, listCatagory: nil, drinkType: "margarita", isList: false, completion: data in
self.parseJSONData(data)
)
extension DrinkViewController
//MARK: JSON parser
fileprivate func parseJSONData(_ jsonData: Data?)
if let data = jsonData
do
let jsonDictionary = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String : AnyObject]//Parses data into a dictionary
// print(jsonDictionary!)
if let drinkDictionary = jsonDictionary!["drinks"] as? [[String: Any]]
for drink in drinkDictionary
let drinkName = drink["strDrink"] as? String ?? ""
let catagory = drink["strCategory"] as? String
let drinkTypeIBA = drink["strIBA"] as? String
let alcoholicType = drink["strAlcoholic"] as? String
let glassType = drink["strGlass"] as? String
let drinkInstructions = drink["strInstructions"] as? String
let drinkThumbnailUrl = drink["strDrinkThumb"] as? String
let cocktailDrink = CocktailModel(drinkName: drinkName, catagory: catagory, drinkTypeIBA: drinkTypeIBA, alcoholicType: alcoholicType, glassType: glassType, drinkInstructions: drinkInstructions, drinkThumbnailUrl: drinkThumbnailUrl)
self.totalDrinksArray.append(cocktailDrink)
catch let error as NSError
print("Error: \(error.localizedDescription)")
DispatchQueue.main.async
self.drinkTableView.reloadData()
//MARK: Image Downloader
func updateImage (imageUrl: String, onSucceed: @escaping () -> Void, onFailure: @escaping (_ error:NSError)-> Void)
//named imageData because this is the data to be used to get image, can be named anything
networkManager.downloadImage(imageUrl: imageUrl, onSucceed: (imageData) in
if let image = UIImage(data: imageData)
self.drinkImage = image
onSucceed()//must call completion handler
) (error) in
onFailure(error)
//MARK: Tableview Delegates
extension DrinkViewController: UITableViewDelegate, UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
//return numberOfRows
return drinksPerPage
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = drinkTableView.dequeueReusableCell(withIdentifier: DRINK_CELL_REUSE_IDENTIFIER) as! DrinkCell
//get image from separate url
if let image = totalDrinksArray[indexPath.row].drinkThumbnailUrl//index out of range error here
updateImage(imageUrl: image, onSucceed:
if let currentImage = self.drinkImage
DispatchQueue.main.async
cell.drinkImage.image = currentImage
, onFailure: (error) in
print(error)
)
cell.drinkLabel.text = totalDrinksArray[indexPath.row].drinkName
return cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
if let image = totalDrinksArray[indexPath.row].drinkThumbnailUrl
updateImage(imageUrl: image, onSucceed:
, onFailure: (error) in
print(error)
)
performSegue(withIdentifier: DRINK_SEGUE, sender: indexPath.row)
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
let lastElement = drinksPerPage
if indexPath.row == lastElement
self.drinkTableView.reloadData()
我看到了这篇文章:tableview-loading-more-cell-when-scroll-to-bottom 并实现了 willDisplay 函数,但出现“索引超出范围”错误。
【问题讨论】:
UITableView load more when scrolling to bottom的可能重复 【参考方案1】:如果您一次获得所有结果,您能告诉我为什么要这样做,那么您不必限制显示,因为它是由 tableview 自动管理的。在 tableview 中,所有的单元格都被重用,所以不会有内存问题。 UITableViewCell 将在显示时创建。
所以不需要限制细胞数。
我现在不知道你在代码中做了什么,但是:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
let lastElement = drinksPerPage // no need to write this line
if indexPath.row == lastElement // if block will never be executed since indexPath.row is never equal to drinksPerPage.
// As indexPath starts from zero, So its value will never be 2.
self.drinkTableView.reloadData()
您的应用程序可能会崩溃,因为您可能只从服务器获取了一项。
如果你真的想加载更多,那么你可以试试这个代码:
声明 numberOfItem 应该等于 drinksPerPage
var numberOfItem = drinksPerPage
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
//return numberOfRows
return numberOfItem
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
if indexPath.row == numberOfItem - 1
if self.totalDrinksArray.count > numberOfItem
let result = self.totalDrinksArray.count - numberOfItem
if result > drinksPerPage
numberOfItem = numberOfItem + drinksPerPage
else
numberOfItem = result
self.drinkTableView.reloadData()
【讨论】:
我只想一次显示特定数量的表格视图单元格,然后用户可以决定是否要加载更多。 @Rahul Dasgupta 还有一个叫做 cmets 的东西。 @SwiftyJD 有什么按钮可以加载更多。 @RahulDasgupta 没有,但是一旦用户滚动到页面底部,它会加载更多。 @SwiftyJD 如果有效,请为我的答案投票。以上是关于限制tableView中显示的单元格数量,滚动到最后一个单元格时加载更多单元格的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 UIImage 从 tableview 单元格中的 url 平滑滚动
tvOS tableView 从一个单元格到另一个单元格平滑滚动