PFQueryTableViewController 分页不适用于 heightForRowAtIndexPath
PFQueryTableViewController pagination doesn't work with heightForRowAtIndexPath
我将 parse.com 框架与 Swift 一起使用,当我在 PFQueryTableViewController 中设置分页时,它不起作用。如果数据库的行数少于 objectPerPage 中设置的数量,它工作正常,但如果有更多的行并且当我 运行 应用程序时它一直显示加载屏幕并且没有下载任何东西,当我 "swipe as refresh" 它崩溃了
错误
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]
ImagesTableViewController.swift
import UIKit
import Parse
import ParseUI
import Bolts
class ImagesTableViewController: PFQueryTableViewController {
@IBAction func unwindToSegue (segue : UIStoryboardSegue) {}
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Configure the PFQueryTableView
self.parseClassName = "Image"
self.pullToRefreshEnabled = true
self.paginationEnabled = true
self.objectsPerPage = 5
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Image")
query.whereKey("deleted", notEqualTo: 1)
query.orderByDescending("createdAt")
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("ImageCell") as! ImageTVCell!
if cell == nil {
cell = ImageTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ImageCell")
}
// Extract values from the PFObject to display in the table cell HEADLINE
if let caption = object?["caption"] as? String {
cell?.headlineLabel?.text = caption
}
// Display image
var initialThumbnail = UIImage(named: "question")
cell.postImageView.image = initialThumbnail
if let thumbnail = object?["image"] as? PFFile {
cell.postImageView.file = thumbnail
cell.postImageView.loadInBackground()
}
return cell
}
// if I remove this code pagination work but the cell height is wrong
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return calculateHeightForRowAtIndexPath(indexPath)
}
func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
println("Ratio: \(ratio)")
return tableView.bounds.size.width / CGFloat(ratio)
} else {
return 50.0
}
}
@IBAction func addNewPhotoButton(sender: UIBarButtonItem) {
self.tabBarController?.tabBar.hidden = true
self.performSegueWithIdentifier("showUploadNewImage", sender: self)
}
}
出现此问题是因为 PFQueryTableViewController
实施了 UITableViewDataSource
中的方法 tableView:numberOfRowsInSection
。我从 GitHub repo containing PFQueryTableViewController.m
copy/pasted
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger count = [self.objects count];
if ([self _shouldShowPaginationCell]) {
count += 1;
}
return count;
}
它只是 returns 要显示的对象的数量(这是有道理的),但是如果启用分页,则需要显示一个额外的单元格。这意味着您必须手动创建另一个包含文本 "Load more data" 或类似内容的单元格,这将触发刷新。
克服这个问题的一种方法是用以下内容覆盖 tableView:numberOfRowsInSection
自己:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.objects!.count
}
更新 1
预建 Parse
分页按钮在之前的答案中消失了
使用以下代码片段计算单元格的高度以显示预建的 Parse
分页按钮
func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
// Special case for pagination, using the pre-built one by Parse
if (indexPath.row >= objects!.count) { return 50.0 }
// Determines the height if an image ratio is present
if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
println("Ratio: \(ratio)")
return tableView.bounds.size.width / CGFloat(ratio)
} else {
return 50.0
}
}
将 Parse 1.11 与 iOS 9.2 和 Xcode 7.2 Parse 分页结合使用可以完美运行。
当用户覆盖 Parse 本身使用的某些功能而没有正确管理 Parse 添加的 "Load More ..." 行时,问题就会浮出水面。
在我的例子中,我需要覆盖 tableView-canEditRowAtIndexPath 以确定当前用户是否可以或不能根据对象的 ACL 删除行。
我的初始功能是:
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if let curUser = PFUser.currentUser() {
let currentObject = objects![indexPath.row]
if let acl = currentObject.ACL {
return acl.getWriteAccessForUser(curUser)
} else {
return true
}
}
return true
}
但在列表滚动期间遇到加载更多行时,我得到了 indexpath out of bounds 的异常。
添加此测试后问题已解决:
if (indexPath.row == self.objects!.count) { // row "Load More ..."
return true
}
如果没有此代码,Parse 将不会添加 "Load More ..." 行!!
所以完整正确的覆盖函数是:
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if (indexPath.row == self.objects!.count) { // row "Load More ..."
return true
}
if let curUser = PFUser.currentUser() {
let currentObject = objects![indexPath.row]
if let acl = currentObject.ACL {
return acl.getWriteAccessForUser(curUser)
} else {
return true
}
}
return true
}
一般来说,包括 heightForRowAtIndexpath 在内的所有重写函数都必须处理启用分页时由 Parse 添加的额外行。
HTH
罗伯托·塔尔加
我将 parse.com 框架与 Swift 一起使用,当我在 PFQueryTableViewController 中设置分页时,它不起作用。如果数据库的行数少于 objectPerPage 中设置的数量,它工作正常,但如果有更多的行并且当我 运行 应用程序时它一直显示加载屏幕并且没有下载任何东西,当我 "swipe as refresh" 它崩溃了 错误
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]
ImagesTableViewController.swift
import UIKit
import Parse
import ParseUI
import Bolts
class ImagesTableViewController: PFQueryTableViewController {
@IBAction func unwindToSegue (segue : UIStoryboardSegue) {}
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Configure the PFQueryTableView
self.parseClassName = "Image"
self.pullToRefreshEnabled = true
self.paginationEnabled = true
self.objectsPerPage = 5
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Image")
query.whereKey("deleted", notEqualTo: 1)
query.orderByDescending("createdAt")
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("ImageCell") as! ImageTVCell!
if cell == nil {
cell = ImageTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ImageCell")
}
// Extract values from the PFObject to display in the table cell HEADLINE
if let caption = object?["caption"] as? String {
cell?.headlineLabel?.text = caption
}
// Display image
var initialThumbnail = UIImage(named: "question")
cell.postImageView.image = initialThumbnail
if let thumbnail = object?["image"] as? PFFile {
cell.postImageView.file = thumbnail
cell.postImageView.loadInBackground()
}
return cell
}
// if I remove this code pagination work but the cell height is wrong
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return calculateHeightForRowAtIndexPath(indexPath)
}
func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
println("Ratio: \(ratio)")
return tableView.bounds.size.width / CGFloat(ratio)
} else {
return 50.0
}
}
@IBAction func addNewPhotoButton(sender: UIBarButtonItem) {
self.tabBarController?.tabBar.hidden = true
self.performSegueWithIdentifier("showUploadNewImage", sender: self)
}
}
出现此问题是因为 PFQueryTableViewController
实施了 UITableViewDataSource
中的方法 tableView:numberOfRowsInSection
。我从 GitHub repo containing PFQueryTableViewController.m
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger count = [self.objects count];
if ([self _shouldShowPaginationCell]) {
count += 1;
}
return count;
}
它只是 returns 要显示的对象的数量(这是有道理的),但是如果启用分页,则需要显示一个额外的单元格。这意味着您必须手动创建另一个包含文本 "Load more data" 或类似内容的单元格,这将触发刷新。
克服这个问题的一种方法是用以下内容覆盖 tableView:numberOfRowsInSection
自己:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.objects!.count
}
更新 1
预建 Parse
分页按钮在之前的答案中消失了
使用以下代码片段计算单元格的高度以显示预建的 Parse
分页按钮
func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
// Special case for pagination, using the pre-built one by Parse
if (indexPath.row >= objects!.count) { return 50.0 }
// Determines the height if an image ratio is present
if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
println("Ratio: \(ratio)")
return tableView.bounds.size.width / CGFloat(ratio)
} else {
return 50.0
}
}
将 Parse 1.11 与 iOS 9.2 和 Xcode 7.2 Parse 分页结合使用可以完美运行。 当用户覆盖 Parse 本身使用的某些功能而没有正确管理 Parse 添加的 "Load More ..." 行时,问题就会浮出水面。 在我的例子中,我需要覆盖 tableView-canEditRowAtIndexPath 以确定当前用户是否可以或不能根据对象的 ACL 删除行。 我的初始功能是:
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if let curUser = PFUser.currentUser() {
let currentObject = objects![indexPath.row]
if let acl = currentObject.ACL {
return acl.getWriteAccessForUser(curUser)
} else {
return true
}
}
return true
}
但在列表滚动期间遇到加载更多行时,我得到了 indexpath out of bounds 的异常。 添加此测试后问题已解决:
if (indexPath.row == self.objects!.count) { // row "Load More ..."
return true
}
如果没有此代码,Parse 将不会添加 "Load More ..." 行!! 所以完整正确的覆盖函数是:
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if (indexPath.row == self.objects!.count) { // row "Load More ..."
return true
}
if let curUser = PFUser.currentUser() {
let currentObject = objects![indexPath.row]
if let acl = currentObject.ACL {
return acl.getWriteAccessForUser(curUser)
} else {
return true
}
}
return true
}
一般来说,包括 heightForRowAtIndexpath 在内的所有重写函数都必须处理启用分页时由 Parse 添加的额外行。
HTH
罗伯托·塔尔加