如何将 UIImages 从相机附加到数组中



我有一个几行的UITableView。当我长按一行时,会弹出一个菜单,我将能够打开相机拍照。 我创建了一个包含照片数组的相册数组。我希望每一行都将捕获的图片保存到我的照片数组中。 当我尝试将照片附加到我的阵列时,崩溃并显示以下行的错误Index out of rangealbumPhotos[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()
}
}

感谢您阅读本文!

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

专辑VC

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

并更改下面的文件相册照片.swift以及

import Foundation
class AlbumPhotos {
var imagesPath: [String]
init(imagesPath: [String]) {
self.imagesPath = imagesPath
}
}
albumPhotos[lastIndexPath.row].imagesPath?.append(nameOfPhoto)

此时,albumPhotos是空的,因此您无法从数组的该位置获取AlbumPhotos对象。

您需要在每个单元格处为索引处的行添加一个对象 相册照片 或者您可以通过将索引作为键来获取字典。

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
}

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

最新更新