I have a UITableView with few rows. When I LongPress on a row then a menu will pop-up and I will be able to open the camera to take a picture.
I've created an array of Albums which contains an array of Photos. I want for each row to save that captured pictures into my array of Photos.
When I try to append the photo to my array is crashing with error Index out of range on this line: albumPhotos[lastIndexPath.row].imagesPath?.append(nameOfPhoto)
Here is a small DEMO which reflect my actual issue: https://github.com/tygruletz/AddPhotosToAlbums
Here is my code:
class AlbumPhotos {
var imagesPath: [String]
init(imagesPath: [String]) {
self.imagesPath = imagesPath
}
}
protocol AlbumCellDelegate {
func longTapGestureOnCell(_ selectedCell: AlbumCell)
}
class AlbumCell: UITableViewCell {
// Interface Links
@IBOutlet weak var albumNameLabel: UILabel!
@IBOutlet weak var photosImageView: CustomImageView!
// Properties
var delegate: AlbumCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longTapPressed(sender:)))
addGestureRecognizer(longTapGesture)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
// Detect when the user press Long Tap on any cell
@objc func longTapPressed(sender: UITapGestureRecognizer) {
delegate?.longTapGestureOnCell(self)
}
}
extension AlbumVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return receivedAlbumsType.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "albumCell", for: indexPath) as! AlbumCell
cell.delegate = self // tell the delegate to report everything to this VC
cell.albumNameLabel.text = receivedAlbumsType[indexPath.row].name.capitalized
if albumPhotos.isEmpty {
cell.photosImageView.isUserInteractionEnabled = false
}
else {
let thumbnailImage = albumPhotos[indexPath.row].imagesPath.last ?? String()
cell.photosImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapOnPhotosImageView)))
cell.photosImageView.indexPath = indexPath
cell.photosImageView.isUserInteractionEnabled = true
cell.photosImageView.image = UIImage(named: thumbnailImage)
print("For section \(indexPath.section) - row \(String(describing: indexPath.row)) the album photos are: \(String(describing: albumPhotos[indexPath.row].imagesPath))")
}
return cell
}
@objc func tapOnPhotosImageView(_ sender: UITapGestureRecognizer){
guard let img = sender.view as? CustomImageView, let indexPath = img.indexPath else {return}
selectedIndexPath = indexPath // Get the index of the clicked album of images
print("Index for selected image: \(selectedIndexPath ?? IndexPath())")
if albumPhotos.isEmpty {
print("No photos in the album.")
}
else{
print("There are photos in the album.")
print(albumPhotos.map {$0.imagesPath})
}
}
}
class AlbumVC: UIViewController {
// Interface Links
@IBOutlet weak var albumsTableView: UITableView!
// Properties
var receivedAlbumsType: [AlbumType] = []
var imagePicker = UIImagePickerController()
var cellImageView = UIImageView()
var selectedIndexPath: IndexPath!
var lastIndexPath: IndexPath!
var albumPhotos: [AlbumPhotos] = []
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
albumsTableView.reloadData()
}
func setupViews(){
albumsTableView.tableFooterView = UIView()
albumsTableView.reloadData()
}
}
extension AlbumVC: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
//Dismiss the Camera and display the selected image into the UIImageView
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
imagePicker.dismiss(animated: true, completion: nil)
guard let selectedImage = info[.originalImage] as? UIImage else {
print("Image not found!")
return
}
let randomNumber = arc4random()
let nameOfPhoto = "photo_\(randomNumber).jpeg"
print("Resolution of captured image before resize: \(selectedImage.size)")
print("Index for lastIndexPath.row: \(lastIndexPath.row)")
albumPhotos[lastIndexPath.row].imagesPath?.append(nameOfPhoto)
print("last images from albumPhotos: \(albumPhotos[lastIndexPath.row].imagesPath?[lastIndexPath.row] ?? String())")
albumsTableView.reloadData()
}
}
Thanks for reading this !
albumPhotos[lastIndexPath.row].imagesPath?.append(nameOfPhoto)