带有图像的PFQueryTableViewController中的动态单元格高度

时间:2015-06-07 16:49:55

标签: ios swift parse-platform pfquerytableviewcontrolle

简单:我希望图片的大小与屏幕宽度和计算的高度保持宽高比,类似于9gag app。

如何在 PFQueryTableViewController 中创建单元格的动态高度,在我的单元格中,我在自定义单元格中有一个标签和PFImageView,并且加载工作正常,但图片是不改变单元格的高度,所有单元格都具有相同的高度。我第三天就遇到了这个问题,它看起来像是来自parse.com框架的错误。当我使用UITableViewController时,我能够改变单元格高度,但是解析框架忽略了它。

使用故事板并尝试使用autolayout约束而没有它。 的 TableViewController.swift

import UIKit
import Parse
import ParseUI
import Bolts
class TableViewController: PFQueryTableViewController {

// 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.pullToRefreshEnabled = true
    self.paginationEnabled = false

}

// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {

    // Start the query object
    var query = PFQuery(className: "Image")
    query.whereKey("deleted", equalTo: 0)
    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("CustomCell") as! CustomTableViewCell!
    if cell == nil {
        cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CustomCell")
    }

    // Extract values from the PFObject to display in the table cell
    if let name = object?["caption"] as? String{
        cell.postHeadlineLabel.text = name
    }

    // display initial image
    var initialThumbnail = UIImage(named: "question")
    cell.postImageView.image = initialThumbnail
    // extract image
    if let thumbnail = object?["image"] as? PFFile {
        cell.postImageView.file = thumbnail
        cell.postImageView.loadInBackground()
    }
    cell.postImageView.contentMode = UIViewContentMode.ScaleAspectFit
    cell.postImageView.clipsToBounds = true

    cell.actualWidth = cell.postImageView.image!.size.width
    cell.actualHeight = cell.postImageView.image!.size.height

    return cell
}


    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell!
        let aspect = cell.actualWidth / cell.actualHeight
        var height: CGFloat = cell.postImageView!.frame.size.width * aspect
        return height
    }
}

CustomTableViewCell.swift

import UIKit
import Parse
import ParseUI
class CustomTableViewCell: PFTableViewCell {
 var actualHeight: CGFloat = 10
 var actualWidth: CGFloat = 10
 @IBOutlet weak var postHeadlineLabel: UILabel!
 @IBOutlet weak var postImageView: PFImageView!
}

我在网上找到了一些建议,但它不起作用,似乎是iOS8解析框架的错误 我试过了

cell.postImageView.contentMode = UIViewContentMode.ScaleAspectFit
cell.postImageView.clipsToBounds = true
cell.sendSubviewToBack(cell.postImageView)

override func awakeFromNib() {
    self.setTranslatesAutoresizingMaskIntoConstraints(false)
}

更新 - 解析数据库https://www.anony.ws/image/D6tp

2 个答案:

答案 0 :(得分:0)

PFQueryTableViewController继承自UITableViewController,这意味着它符合UITableViewDelegate协议。在这里有一个你可以覆盖的方法叫做:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat

在此处,您应该返回特定的CGFloat(例如50.0f代表50px或其他内容),具体取决于indexPath指定的特定单元格的大小。

更新1

OP提供了更多代码来阐述问题

由于您在tableView.dequeueReusableCellWithIdentifier中呼叫tableView:heightForRowAtIndexPath,这意味着一旦您有一个准备好图像的单元格,那么它将一遍又一遍地使用此宽高比。您tableView.dequeueReusableCellWithIdentifier中的逻辑与所提供的indexPath中的唯一对象无关。

解决此问题的一种方法是调用objectAtIndexPath(indexPath),这是PFQueryTableViewController的方法。这样,您就可以访问指定单元格中的PFObjectPFFile。这样做的缺点是你必须再次下载图像,因此需要使用大量的带宽。它还会降低您的应用速度,因为您必须等待它下载。

您还可以使用tableView.cellForRowAtIndexPath(indexPath)为该单元格获取一些独特内容,但不幸的是tableView:heightForRowAtIndexPathtableView:cellForRowAtIndexPath之前调用了PFQueryTableViewController,这将导致该应用崩溃。

我最好的建议是为您的Image类添加另一个字段,用于存储图像的宽高比。

如果由于你已经拥有一个大型数据库或其他一些好的理由而无法做到这一点,那么我建议你制作一个可以计算宽高比的云功能。

更新2

更新了解决方案

坐下来玩了一会儿后,我设法找到了解决问题的方法。不幸的是它并不漂亮,我仍然建议你将数据库模式中的宽高比存储为最佳解决方案。

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return calculateHeightForRowAtIndexPath(indexPath);
}

func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
    if let file = objectAtIndexPath(indexPath)?["image"] as? PFFile {
        let image = UIImage(data: file.getData()!)
        let imageToScreenRatio = tableView.bounds.size.width / (image?.size.width)!
        return imageToScreenRatio * (image?.size.height)!
    }
    else {
        return 50.0
    }
}

这真的很糟糕的原因是因为使用file.getData()在主UI线程中下载了图像。相反应该使用file.getDataInBackgroundWithBlock(block),但这会导致问题,因为calculateHeightForRowAtIndexPath会在下载图像之前返回。

更新3

OP提供了有关数据库架构的更多信息

由于您已经在数据库中存储了比率,因此您可以通过以下方式计算单元格高度:

func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
    if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
        return tableView.bounds.size.width / CGFloat(ratio)
    }
    else {
        return 50.0
    }
}

答案 1 :(得分:0)

您正在实施的是一种错误的方法。 在cellForRowAtIndexPath之前调用heightForRowAtIndexPath。因此,它会在您的方法中返回错误的值。尝试使用设备宽度。根据我对您的要求的理解,我在下方做了更改。尝试并相应地做一些更改,让我知道它是否有效..

在你的heightForRowAtIndexPath中,尝试更改

#define ASPECT_RATIO 0.5f
var height: CGFloat = UIScreen.mainScreen().bounds.size.width * ASPECT_RATIO

这个会使单元格的高度为设备宽度的一半。 您可以根据需要更改宽高比的值。如果您有标签,可以在高度变量中添加它的高度。