Simple: I want the size of the picture with width of the screen and the height calculated to keep the aspect ratio, similar to 9gag app.
How can I make dynamic height of cell in PFQueryTableViewController, in my cell I have one label and PFImageView in a Custom cell and loading works fine, but the pictures are not changing the height of the cell and all of the cells have the same height. I am stuck on this problem for third day and it looks like error from the parse.com framework. I was able to change the cell height when I was working with UITableViewController but the parse framework ignores it.
I am using storyboard and tried that with autolayout constraint and without it. 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!
}
I found some advices online but it doesnt work and seems like error of the parse framework with iOS8 I tried
cell.postImageView.contentMode = UIViewContentMode.ScaleAspectFit
cell.postImageView.clipsToBounds = true
cell.sendSubviewToBack(cell.postImageView)
or
override func awakeFromNib() {
self.setTranslatesAutoresizingMaskIntoConstraints(false)
}
Update - parse DB: https://www.anony.ws/image/D6tp
PFQueryTableViewController
inherits fromUITableViewController
, which means it conforms to theUITableViewDelegate
protocol. Inside here there is a method that you can override called:In here you should return a specific
CGFloat
(for example50.0f
for 50px or something else) depending on the size of that specific cell given by theindexPath
.UPDATE 1:
OP provided more code to elaborate the issue
Since you are calling
tableView.dequeueReusableCellWithIdentifier
in thetableView:heightForRowAtIndexPath
, then it means that once you've got one cell with an image ready, then it'll keep using this aspect ratio over and over. There is no logic in yourtableView.dequeueReusableCellWithIdentifier
which is tied to the unique object at the providedindexPath
.One way to overcome this could be by calling
objectAtIndexPath(indexPath)
, which is a method fromPFQueryTableViewController
. This will give you access to thePFObject
andPFFile
at the specified cell. The downside to this is that you'll have to download the image again, thus using a lot of band-width. It will also slow down your app since you'll have to wait for it to download.You could also make use of
tableView.cellForRowAtIndexPath(indexPath)
to get something unique for that cell, but unfortunatelytableView:heightForRowAtIndexPath
is called beforetableView:cellForRowAtIndexPath
in thePFQueryTableViewController
which will cause the app to crash.My best suggestion is to add another field to the database for your
Image
class which stores the aspect ratio of the image.If this is not possible since you already have a large database or some other good reason, then I would recommend for you to make a cloud function which can compute the aspect ratio.
UPDATE 2
Updated solution to answer
After sitting and playing around with it for a while, then I managed to come up with a solution for your issue. Unfortunately it is not pretty and I will still suggest you to store the aspect ratio in your DB schema as the most optimal solution.
The reason why this is really bad is because the image is being downloaded in the main UI thread using
file.getData()
. Insteadfile.getDataInBackgroundWithBlock(block)
should be used, but this would cause problems sincecalculateHeightForRowAtIndexPath
would then return before having downloaded the image.UPDATE 3
OP provided more info on DB schema
Since you already have the ratio stored in the database, then you can calculate the cell height the following way: