So in my app I currently have a tableView with custom cells that have an imageView in them. Here is an image for reference to see what It look like and here is the code that defines the custom cell:
class GearComponentTableViewCell: UITableViewCell {
var delegate:Stepper?
var tableViewCellPosition: Int! = nil
// Image
@IBOutlet weak var itemImage: UIImageView!
// Name
@IBOutlet weak var itemName: UILabel!
// Weight
@IBOutlet weak var itemWeight1: UILabel!
@IBOutlet weak var itemWeight2: UILabel!
// Quanity
@IBOutlet weak var itemQuanity: UILabel!
@IBAction func stepperPressed (_ sender: UIStepper!) {
if (sender.value == 1) {
sender.value = 0
delegate?.stepperWasPressed(didIncrease: true, namePassed: itemName.text!, userindexPath: tableViewCellPosition)
} else if (sender.value == -1) {
sender.value = 0
delegate?.stepperWasPressed(didIncrease: false, namePassed: itemName.text!, userindexPath: tableViewCellPosition)
}
}
// Notes
@IBOutlet weak var itemNotes: UILabel!
}
These cells are tappable and when tapped they present an alert with options for adding an image to the cell you chose:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("User selected item: \(indexPath.row) and name is \(itemArray[indexPath.row].name)")
showPopUp(itemChosen: indexPath)
}
Here is the logic for the pop up/Alert:
func showPopUp(itemChosen: IndexPath) {
let alert = UIAlertController(title: "Add Photo To Item", message: .none, preferredStyle: .actionSheet)
// alert actions
let action1 = UIAlertAction(title: "Take Photo", style: .default) { action in
self.takePhoto()
}
let action2 = UIAlertAction(title: "Import Photo", style: .default) { action in
self.importPhoto(position: itemChosen)
}
let action3 = UIAlertAction(title: "Cancel", style: .destructive)
alert.addAction(action1)
alert.addAction(action2)
alert.addAction(action3)
present(alert, animated: true,completion: nil)
}
Ignore the takePhoto()
function because it isn't being used yet, but right below that I am calling the importPhoto()
function that takes in the position of the item you selected:
func importPhoto(position: IndexPath) {
print("User chose to import photo")
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true) {
print("cell tapped \(position)")
self.cellChosen = position
}
}
It then sets a global variable to the item you selected (I know this isn't a good practice vs. passing the actual indexPath) that I use to pass into the imagePickerControllerDelegate function:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
dismiss(animated: true)
if let cell = tableView(gearTableView, cellForRowAt: cellChosen) as? GearComponentTableViewCell {
cell.itemImage.image = image
self.updateUI()
print("item image set for the item at position: \(cellChosen.row)")
}else {
print("did not set item image")
}
}
This is where I am running into issues now. When that delegate function gets called it successfully prints the true-case in the if/else statement and the photo isn't actually being set and I'm not receiving any errors at the time it is set. The only error I receive is "Changing the translatesAutoresizingMaskIntoConstraints property of a UICollectionViewCell that is managed by a UICollectionView is not supported, and will result in incorrect self-sizing."
when I tap the right bar-button item from the first photo in my post to add a new cell to the tableView. I require some info in the form of another Alert with textfields for some info about the item you are creating before the cell is actually created to I'm not sure if that error is actually relevant to what I am currently working on.
Any ideas as to how I can set the image of the imageView in my cell? I've already tried changing the Layout
of my imageView from Inferred (constraints)
to Auto-resizing mask
and any new cells stopped appearing...
Here is a link to my repository/the viewController I was working in.
CodePudding user response:
Change your implementation of method imagePickerController(_ picker:didFinishPickingMediaWithInfo:) to
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
picker.dismiss(animated: true)
itemArray[cellChosen.row].image = image
gearTableView.reloadRows(at: [cellChosen], with: .none)
}
When you need to update an image of a data source model. You update the model and call reload row.
About why your code doesn't work, set a breakpoint at func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
, and you will find your imageView's image is beening reset in above method.
CodePudding user response:
It's because you're not updating the image on the data source of the table view. You update when you dequeue the cell, but the you call updateUI that calls reloadData().
For instance, your method imagePickerController can work like this:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
dismiss(animated: true)
let item = itemArray[cellChosen.row]
let userSubmittedItem = GearItem(itemName: item.name,
itemImage: image,
itemWeight1: item.weight1,
itemWeight2: item.weight2,
itemQuantity: item.quantity,
itemNotes: item.notes)
itemArray[cellChosen.row] = userSubmittedItem
self.updateUI()
}