PFQueryTableViewController分页不适用于heightForRowAtIndexPath

时间:2015-06-09 11:34:02

标签: ios swift parse-platform pagination pfquerytableviewcontrolle

我正在使用Swift的parse.com框架和PFQueryTableViewController,当我设置分页时它将无法正常工作。如果数据库的行数少于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)
}

}

2 个答案:

答案 0 :(得分:1)

出现此问题的原因是PFQueryTableViewControllertableView:numberOfRowsInSection实施了方法UITableViewDataSource。我已经从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分页按钮在之前的回答中消失了

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

答案 1 :(得分:0)

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

覆盖func tableView(tableView:UITableView,canEditRowAtIndexPath indexPath:NSIndexPath) - >布尔{

    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) - >布尔{

    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在内的所有重写的func必须在启用分页时处理Parse添加的额外行。

HTH

Roberto Targa