【问题标题】:PFQueryTableViewController pagination doesn't work with heightForRowAtIndexPathPFQueryTableViewController 分页不适用于 heightForRowAtIndexPath
【发布时间】:2015-06-09 11:34:01
【问题描述】:

我在 Swift 和 PFQueryTableViewController 中使用 parse.com 框架,当我设置分页时它不起作用。如果数据库的行数少于 objectPerPage 中设置的行数,则它可以正常工作,但是如果行数更多并且当我运行应用程序时,它会一直显示加载屏幕并且没有下载任何内容,当我执行“刷新时滑动”时,它会崩溃为 错误

*** 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)
}

}

【问题讨论】:

    标签: ios swift parse-platform pagination pfquerytableviewcontrolle


    【解决方案1】:

    出现此问题是因为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;
    }
    

    它只是返回要显示的对象的数量(这是有道理的),但是如果启用了分页,则需要显示一个额外的单元格。这意味着您必须手动创建另一个带有文本“加载更多数据”或类似内容的单元格,这会触发刷新。


    解决这个问题的方法是简单地使用以下内容覆盖tableView:numberOfRowsInSection

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.objects!.count
    }
    

    更新 1

    预建的Parse 分页按钮在上一个答案中消失了


    使用以下代码sn-p计算单元格的高度以显示预建的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
        }
    }
    

    【讨论】:

    • 谢谢你的回复,我说的对吗:如果我用“刷新”功能手动创建单元格我也可以设置self.paginationEnabled = false?问题是,当我删除 override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return calculateHeightForRowAtIndexPath(indexPath) } 时,该应用程序运行良好,但单元格高度搞砸了,最后一个单元格是单元格加载更多。我不明白的是, heightForRowAtIndexPath 只是计算单元格高度,所以它为什么禁用分页...
    • 您必须在其他方法之间插入上述方法的代码 sn-p。我将编辑答案以反映这一点。
    • 测试您发布的代码是我做的第一件事screenshot,但最后一个加载更多数据的单元格没有显示...
    • @Kumuluzz 我刚刚在这里和 Mazel 的另一篇文章中完成了你的回答,我想我也有类似的问题,但我使用的是普通的 TVC 而不是 PFQTVC 我也在使用 UITableViewAutomaticDimension 来调整我的大小单元格,但它似乎无法正常工作(如果您愿意,可以查看我的最新问题)任何帮助或建议将不胜感激! :)
    • @Theo,这个问题与你的问题无关。这个问题是关于分页的,而你的问题是关于动态调整单元格的大小。但是请随时附上特定问题的链接,然后我会看看
    【解决方案2】:

    在 iOS 9.2 和 Xcode 7.2 中使用 Parse 1.11 Parse Pagination 可以完美运行。 当用户在没有正确管理 Parse 添加的“Load More ...”行的情况下覆盖 Parse 本身使用的某些函数时,问题就会浮出水面。 在我的情况下,我需要覆盖 tableView-canEditRowAtIndexPath 以确定当前用户是否可以根据对象的 ACL 删除该行。 我最初的功能是:

    覆盖 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
    }
    

    但是当在列表滚动期间遇到 Load More 行时,我得到了 indexpath 越界的异常。 添加此测试后问题已解决:

        if (indexPath.row == self.objects!.count) { // row "Load More ..."
            return true
        }
    

    如果没有此代码,Parse 不会添加“加载更多...”行! 所以完整正确的覆盖函数是:

    覆盖 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

    罗伯托·塔加

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-12
      • 2014-09-10
      相关资源
      最近更新 更多