如何将Camera中的UIImage附加到数组中

时间:2019-05-17 13:10:12

标签: ios swift

我有一个UITableView,只有几行。当我在一行上长按时,将弹出一个菜单,我将可以打开相机拍照。 我创建了一个相册数组,其中包含一个照片数组。我希望每一行将捕获的图片保存到我的“照片”数组中。 当我尝试将照片添加到阵列时,在此行上发生错误Index out of range的崩溃:albumPhotos[lastIndexPath.row].imagesPath?.append(nameOfPhoto)

这里有一个小演示,反映了我的实际问题:https://github.com/tygruletz/AddPhotosToAlbums

这是我的代码:

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()
    }
}

谢谢阅读!

3 个答案:

答案 0 :(得分:1)

我在您的代码中更改了以下文件。因此,请替换这些文件并检查您的应用并分享您的反馈。

AlbumVC.swift

import UIKit

class AlbumVC: UIViewController {

    // Interface Links
    @IBOutlet weak var albumsTableView: UITableView!

    // Properties
    var imagePicker = UIImagePickerController()
    var cellImageView = UIImageView()
    var albumPhotos = [AlbumPhotos]()
    var selectedIndexPath: IndexPath!
    var lastIndexPath: IndexPath!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        albumPhotos = DataModel.instance.getAlbumPhotosData(numberOfData: 10)
    }

    func setupViews(){
        albumsTableView.tableFooterView = UIView()
        albumsTableView.reloadData()
    }
}


extension AlbumVC: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return albumPhotos.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

        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})
        }
    }
}

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 )")

        albumsTableView.reloadData()
    }
}

extension AlbumVC: AlbumCellDelegate {

    // Delegate function to detect on which cell was pressed a LongTapGesture
    func longTapGestureOnCell(_ selectedCell: AlbumCell) {
        showOptionsOnCellTapped(albumsTableView.indexPath(for: selectedCell)!)
    }

    func showOptionsOnCellTapped(_ indexPath: IndexPath) {
        let addPhoto = UIAlertAction(title: " Add Photo", style: .default) { action in
            self.lastIndexPath = indexPath
            print("Add Photo - LastIndexPath: \(self.lastIndexPath ?? IndexPath())")

            self.showCamera(imagePicker: self.imagePicker)
        }

        let actionSheet = configureActionSheet()
        actionSheet.addAction(addPhoto)
        self.present(actionSheet, animated: true, completion: nil)
    }

    // Open camera
    func showCamera(imagePicker: UIImagePickerController) {

        imagePicker.delegate = self
        imagePicker.sourceType = .camera
        present(imagePicker, animated: true, completion: nil)
    }

    // Configure an UIActionSheet to work for iPhone and iPad. If the user use an iPad then the ActionSheet will be displayed in the middle of the screen.
    func configureActionSheet() -> UIAlertController {
        let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        let cancel = UIAlertAction(title: "Cance;", style: .cancel, handler: nil)
        actionSheet.addAction(cancel)

        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad ){
            actionSheet.popoverPresentationController?.sourceView = self.view
            actionSheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
            actionSheet.popoverPresentationController?.permittedArrowDirections = []
        }
        return actionSheet
    }  
}

并添加了此文件以为您的应用 DataModel.Swift

创建黑色数据
class DataModel {

    static let instance = DataModel()

    private init() {

    }

    func getAlbumPhotosData(numberOfData: Int) -> [AlbumPhotos] {

        var albumPhotos = [AlbumPhotos]()

        for _ in 1...numberOfData {
            let objAlbum = AlbumPhotos(imagesPath: [])
            albumPhotos.append(objAlbum)
        }

        return albumPhotos
    }
}

,并在文件 AlbumPhotos.swift 下进行更改

import Foundation

class AlbumPhotos {

    var imagesPath: [String]

    init(imagesPath: [String]) {

        self.imagesPath = imagesPath
    }
}

答案 1 :(得分:0)

  albumPhotos[lastIndexPath.row].imagesPath?.append(nameOfPhoto)

那时,albumPhotos为空,因此无法从该数组位置获得AlbumPhotos对象。

您需要在每个单元格的索引行中添加一个AlbumPhotos对象 或者您可以通过将索引作为关键字来选择字典。

答案 2 :(得分:0)

class AlbumPhotos {

    var imagesPath: [UIImage]

    init(imagesPath: [UIImage]) {

        self.imagesPath = imagesPath
    }
}


extension AlbumVC: AlbumTypeVCDelegate {

    func receivedAlbumType(name: String) {
        albumPhotos.append(AlbumPhotos(imagesPath: [UIImage]()))
        receivedAlbumsType.append(AlbumType(name: name))
    }
}

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(selectedImage)

//        print("last images from albumPhotos: \(albumPhotos[lastIndexPath.row].imagesPath.last ?? String())")

        albumsTableView.reloadData()
    }
}


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 ?? UIImage()
            cell.photosImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapOnPhotosImageView)))
            cell.photosImageView.indexPath = indexPath
            cell.photosImageView.isUserInteractionEnabled = true
            cell.photosImageView.image = thumbnailImage//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
    }

请尝试在您的项目中更改以上代码。