0

I'm trying to download an image and place it in a custom cell, which contains the UIImage and UITextView. I need it to equal to the width of the screen and have the height proportional, similar to this question but I am not sure how to use this convert the answer to use custom table cells. While trying to set the image width and height in tableView:cellForRowAt calling the cell.storedImage.frame.width and height Xcode says it is only a get-only property. This is what I thought would work

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableData[indexPath.row]["Image"] != nil {
        let cell = tableView.dequeueReusableCell(withIdentifier: "imageNotesData", for: indexPath) as! ImageNotesCell
        cell.notes.delegate = self
        cell.notes.tag = indexPath.row
        cell.notes.text = tableData[indexPath.row]["Notes"] as! String
        guard let imageFirebasePath = tableData[indexPath.row]["Image"] else {
            return cell }
        let pathReference = Storage.storage().reference(withPath: imageFirebasePath as! String)
        pathReference.getData(maxSize: 1 * 1614 * 1614) { data, error in
            if let error = error {
                print(error)
            } else {
                //let image = UIImage(data: data!)
                //cell.storedImage.image = image


                let containerView = UIView(frame: CGRect(x:0,y:0,width:self.view.frame.width
                    ,height:500))
                let imageView = UIImageView()
                if let image = UIImage(data:data!) {
                    let ratio = image.size.width / image.size.height
                    if containerView.frame.width > containerView.frame.height {
                        let newHeight = containerView.frame.width / ratio
                        imageView.frame.size = CGSize(width: containerView.frame.width, height: newHeight)
                        cell.storedImage.frame.height = newHeight
                    }
                    else{
                        let newWidth = containerView.frame.height * ratio
                        imageView.frame.size = CGSize(width: newWidth, height: containerView.frame.height)
                        cell.storedImage.frame.width = newWidth
                    }
                }
                let image = UIImage(data: data!)
                cell.storedImage.image = image
            }
        }
        return cell
    }
    else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "notesData", for: indexPath) as! NotesCell
        //let noteString = tableData[indexPath.row]["Notes"] as! String
        cell.notes.text = tableData[indexPath.row]["Notes"] as! String
        cell.notes.delegate = self
        cell.notes.tag = indexPath.row
        return cell
    }
}

I have also tried using auto layout to fix the problem by having the a text view below it have two different bottom margin constraints but it still doesn't look right. This is the closet I gotten with auto layout constraints. Currently the image view has 0 space constraints on every side to super view

enter image description here

I assume that the code snippet is the path I should go with but I am not sure how to make the image to look right.

LampPost
  • 856
  • 11
  • 30

1 Answers1

1

You could still use dynamic constraints, once you get your image you set the aspect ratio constraint for your uiimageview, but it would probably end up being more of a hassle to do.

you can also do this with the frame directly, but you'll need to make a new CGRect for the frame, you can't simply edit it's width or height directly.

you should also set the height of the row to be correct

tableView(_:heightForRowAt:)

I'm assuming you've got your ImageNotesCell has it's default size set in the initialiser with notes some kind of uitextfield/uitextview inherited class and storedImage simply an image

class ImageNotesCell: UITableViewCell {
  func setImage(_ image: UIImage) {
    let previousNotesFrame = notes.frame
    let ratio = image.size.height / image.size.width
    storedImage.image = image
    let newImageFrame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.width * ratio)
    let newNotesFrame = CGRect(x: 0, y: newImageFrame.size.height + your_spacing_here, width: frame.size.width, height: previousNotesFrame.size.height)
    frame = CGRect(x: 0, y: 0, width: frame.size.width, height: newImageFrame.size.height + your_spacing_here + newNotesFrame.size.height)
    storedImage.frame = newImageFrame
    notes.frame = newNotesFrame
  }
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableData[indexPath.row]["Image"] != nil {
        let cell = tableView.dequeueReusableCell(withIdentifier: "imageNotesData", for: indexPath) as! ImageNotesCell
        cell.notes.delegate = self
        cell.notes.tag = indexPath.row
        cell.notes.text = tableData[indexPath.row]["Notes"] as! String
        guard let imageFirebasePath = tableData[indexPath.row]["Image"] else {
            return cell }
        let pathReference = Storage.storage().reference(withPath: imageFirebasePath as! String)
        pathReference.getData(maxSize: 1 * 1614 * 1614) { data, error in
            if let error = error {
                print(error)
            } else {
                let image = UIImage(data: data!)
                cell.setImage(image)
            }
        }
        return cell
    }
    else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "notesData", for: indexPath) as! NotesCell
        //let noteString = tableData[indexPath.row]["Notes"] as! String
        cell.notes.text = tableData[indexPath.row]["Notes"] as! String
        cell.notes.delegate = self
        cell.notes.tag = indexPath.row
        return cell
    }
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if tableData[indexPath.row]["Image"] != nil {
        guard let imageFirebasePath = tableData[indexPath.row]["Image"] else {
            return your_default_height_here }
        let pathReference = Storage.storage().reference(withPath: imageFirebasePath as! String)
        pathReference.getData(maxSize: 1 * 1614 * 1614) { data, error in
            if let error = error {
                print(error)
            } else {
                let image = UIImage(data: data!)
                let ratio = image.size.height / image.size.width
                return (tableView.frame.size.width * ratio) + your_spacing_value_here + your_notes_height_here
            }
        }
    } else {
        return your_notes_cell_height_here
    }
}

I tested the logic on a custom UITableViewCell I made and with 3 different image dimensions and notes. it fills up the screen. but since I don't know you ImageNotesCell class among other things I'll leave it to you to adapt but here's the gist of it:

ImageNotesCell class:

  • add a function to set an image to the cell which will in turn update the cell, the note and image's frames

Controller class:

  • cellForRow: initialise your cell, set it up as usual for the notes part and for when there aren't any images, call the setImage method, return your cell
  • heightForRow: return the usual height for when there isn't an image to load, get your image, calculate it's height/width ratio, multiply that by the tableView width, add the value for your spacing, add the height of your notes
James Woodrow
  • 365
  • 1
  • 14