How can I save multiple images which are picked from the UIPickerController? - swift

All the images which I'm uploading in the app (with the UIImagePickerController) are showing in the app but when I'm closing the app the images disappear. I used UserDefaults for one image (without the UICollectionView) and the code worked (see the code) but when i used the UICollectionView, the code does not work anymore. It would be nice if anyone can help me or give me some tips!
import UIKit
class wardrobeViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var allImagesCollection: UICollectionView!
var collectionViewClass = CollectionViewCell()
var theUploadedImg = UIImageView()
let userDefault = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
allImagesCollection.delegate = self
allImagesCollection.dataSource = self
collectionViewClass.newImage = theUploadedImg
let imageData = userDefault.object(forKey: "thePickedImage") as? NSData
if let imageData = imageData {
let image = UIImage(data: imageData as Data)
theUploadedImg.image = image
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func chooseImage(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "", message: "Choose an image from", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action: UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
imagePickerController.sourceType = UIImagePickerControllerSourceType.camera
imagePickerController.allowsEditing = false
self.present(imagePickerController, animated: true, completion: nil)
}
}))
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action: UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
imagePickerController.sourceType = UIImagePickerControllerSourceType.photoLibrary
imagePickerController.allowsEditing = false
self.present(imagePickerController, animated: true, completion: nil)
}
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
var newPickedImage = [UIImage]()
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
theUploadedImg.contentMode = .scaleToFill
theUploadedImg.image = pickedImage
newPickedImage.append(pickedImage)
let pickedImageData = UIImagePNGRepresentation(pickedImage)
userDefault.set(pickedImageData, forKey: "thePickedImage")
}
picker.dismiss(animated: true, completion: nil)
allImagesCollection.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return newPickedImage.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
cell.newImage.image = newPickedImage[indexPath.item]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 0.5
return cell
}
let cellsPerRow = 3
override func viewWillLayoutSubviews() {
guard let collectionView = allImagesCollection, let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
let marginsAndInsets = flowLayout.sectionInset.left + flowLayout.sectionInset.right + collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right + flowLayout.minimumInteritemSpacing * CGFloat(cellsPerRow - 1)
let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down)
flowLayout.itemSize = CGSize(width: itemWidth, height: itemWidth)
}
}

You are saving only 1 image to UserDefaults. In order to persist these images, you have to save all of them, not just override 1 image. Also, on application start you have to fetch all of the images and reload UICollectionView with them.
One more tip, do not save images to UserDefaults, use FileManager.

Related

how to call/show action sheet for taking or choose photo from gallery on Main VC after tapped on TableViewCell Image(swift)

Here I Try MVVM pattern to achieve TableView but for showing alert I face problems , it compiles successfully but not showing alert.
[Result] on the tapped on profile pic which is in tableview cell, I want to show alert
TableViewCell
import Foundation
import UIKit
class ParentsImageCell : UITableViewCell {
weak var myVC : ProfileOfParentsDetailsViewController?
var parentProfileVC = ProfileOfParentsDetailsViewController()
#IBOutlet weak var imageProfile : UIImageView!
var items : ParentProfileViewModelItem? {
didSet {
guard let items = items as? ParentProfileViewModelProfileItem else {
return
}
imageProfile?.image = UIImage(named: items.profileImg)
}
}
static var nib:UINib {
return UINib(nibName: identifier, bundle: nil)
}
static var identifier: String {
return String(describing: self)
}
override func awakeFromNib() {
super.awakeFromNib()
imageProfile?.layer.cornerRadius = 62
imageProfile?.clipsToBounds = true
imageProfile?.contentMode = .scaleAspectFill
imageProfile?.backgroundColor = UIColor.lightGray
//Add Tapped Gesture
imageProfile.isUserInteractionEnabled = true
let gesture = UITapGestureRecognizer(
target: self,
action: #selector(didTappedChangeProfilePic))
gesture.numberOfTapsRequired = 1
gesture.numberOfTouchesRequired = 1
imageProfile.addGestureRecognizer(gesture)
}
#objc private func didTappedChangeProfilePic(){
print("tapped on imageView")
presentPhotoActionSheet()
}
override func prepareForReuse() {
super.prepareForReuse()
imageProfile?.image = nil
}
}
extension ParentsImageCell : UIImagePickerControllerDelegate ,UINavigationControllerDelegate {
func presentPhotoActionSheet(){
let actionSheet = UIAlertController(title: "Profile Picture", message: "How would you write to select a picture", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "cancel", style: .cancel, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Take Photo", style: .default, handler: {[weak self] _ in
self?.presentCamera()
}))
actionSheet.addAction(UIAlertAction(title: "Choose Photo", style: .default, handler: { [weak self]_ in
self?.presentPhotoPicker()
}))
myVC?.present(actionSheet , animated: true)
}
func presentCamera(){
let vc = UIImagePickerController()
vc.sourceType = .camera
vc.delegate = self
vc.allowsEditing = true
myVC?.present(vc , animated: true)
}
func presentPhotoPicker(){
let vc = UIImagePickerController()
vc.sourceType = .photoLibrary
vc.delegate = self
vc.allowsEditing = true
myVC?.present(vc , animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:
[UIImagePickerController.InfoKey : Any]) {
guard let selectedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else {
return
}
self.imageProfile.image = selectedImage
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
ViewModel
class ParentProfileViewModel: NSObject {
var items = [ParentProfileViewModelItem]()
var reloadSections: ((_ section: Int) -> Void)?
override init() {
super.init()
guard let data = dataFromFile("ServerData"),
let profile = Profile(data: data) else {
return
}
// initialization code will go here
if let profile = profile.pictureUrl {
let profileItem = ParentProfileViewModelProfileItem(profileImg: profile)
items.append(profileItem)
}
if let name = profile.fullName {
let nameItem = ParentProfileViewModelNameItem(name: name)
items.append(nameItem)
}
if let email = profile.email {
let emailItem = ParentProfileViewModelEmailItem(email: email)
items.append(emailItem)
}
let coach = profile.coach
if !coach.isEmpty {
let coachItem = ParentProfileViewModelCoachItem(coach: coach)
items.append(coachItem)
}
let candidate = profile.candidate
if !candidate.isEmpty {
let candidateItem = ParentProfileViewModelCandidateItem(candidate: candidate)
items.append(candidateItem)
}
}
}
//MARK:- TableviewDatasource & Delegates
extension ParentProfileViewModel: UITableViewDataSource {
//Number of section
func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
//Number of RowInSection
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let item = items[section]
guard item.isCollapsible else {
return item.rowCount
}
if item.isCollapsed {
return 0
} else {
return item.rowCount
}
}
//Cell for row at indexpath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// we will configure the cells here
let item = items[indexPath.section]
switch item.type {
case .profileImg:
let vc = ProfileOfParentsDetailsViewController()
if let cell = tableView.dequeueReusableCell(withIdentifier: ParentsImageCell.identifier, for: indexPath) as? ParentsImageCell {
cell.items = item
cell.myVC = vc
return cell
}
case .fullName:
if let cell = tableView.dequeueReusableCell(withIdentifier: ParentsFulNameCell.identifier, for: indexPath) as? ParentsFulNameCell {
cell.items = item
return cell
}
case .email:
if let cell = tableView.dequeueReusableCell(withIdentifier: ParentsEmailCell.identifier, for: indexPath) as? ParentsEmailCell {
cell.items = item
return cell
}
case .candidate:
if let item = item as? ParentProfileViewModelCandidateItem, let cell = tableView.dequeueReusableCell(withIdentifier: CandidatCell.identifier, for: indexPath) as? CandidatCell {
let candidate = item.candidate[indexPath.row]
cell.item = candidate
return cell
}
case .coach:
if let item = item as? ParentProfileViewModelCoachItem, let cell = tableView.dequeueReusableCell(withIdentifier: ParentCoachCell.identifier, for: indexPath) as? ParentCoachCell {
cell.item = item.coach[indexPath.row]
return cell
}
}
return UITableViewCell()
}
}
ViewController
import Foundation
import UIKit
class ProfileOfParentsDetailsViewController: UIViewController {
let viewModel = ParentProfileViewModel()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
viewModel.reloadSections = { [weak self] (section: Int) in
self?.tableView?.beginUpdates()
self?.tableView?.reloadSections([section], with: .fade)
self?.tableView?.endUpdates()
}
tableView?.dataSource = viewModel
tableView.delegate = viewModel
tableView?.estimatedRowHeight = 250
tableView?.rowHeight = UITableView.automaticDimension
tableView?.register(ParentsImageCell.nib, forCellReuseIdentifier: ParentsImageCell.identifier)
tableView?.register(ParentsEmailCell.nib, forCellReuseIdentifier: ParentsEmailCell.identifier)
tableView?.register(ParentsFulNameCell.nib, forCellReuseIdentifier: ParentsFulNameCell.identifier)
tableView?.register(CandidatCell.nib, forCellReuseIdentifier: CandidatCell.identifier)
tableView?.register(ParentCoachCell.nib, forCellReuseIdentifier: ParentCoachCell.identifier)
tableView?.register(ParentsHeaderView.nib, forHeaderFooterViewReuseIdentifier: ParentsHeaderView.identifier)
}
I try to get called alert Sheet , but I Failed and also comment about my approach towards MVVM
I try to called the tableview data source and delegate in VM
I try to get called alert Sheet , but I Failed and also comment about my approach towards MVVM
I try to called the tableview data source and delegate in VM

when fetch images from firebase, tableView not scroll to row Swift

I begin to create a chat app and want it to scroll to bottom every time I enter text or image. For text, the code is perfect to execute scrollToRow after tableView reload. However, the image always shows under the keyboard, I tried many ways to solve this issue but still get the same result.
image does not show above the keyboard
image is under keyboard
class ChatTableViewController: UITableViewController, UITextViewDelegate {
private let reuseIdentifier = "reuseIdentifier"
private let chatImageIdentifier = "chatImageCell"
var sSection = 0
var rRow = 0
var commentRef: DatabaseReference!
var firebaseHandle: DatabaseHandle?
var dataSnapshot: DataSnapshot?
let uid = FirebaseHelper.shared.getUserId()
let username = FirebaseHelper.shared.getUsername()
let email = FirebaseHelper.shared.getUserEmail()
var comments = [Comment]()
var intArray: [Int]? {
didSet{
guard let intArray = intArray else {return}
self.sSection = intArray[0]
self.rRow = intArray[1]
commentRef = FirebaseHelper.shared.getCommentRef(firebaseRef: .comments, section: sSection, row: rRow)
comments = []
tableView.reloadData()
observeCommentsFromFirebase {
}
setUpKeyboardObserver()
}
}
func observeCommentsFromFirebase(completion: #escaping (()->Void)) {
firebaseHandle = commentRef.queryOrdered(byChild: "timeStamp").observe(.childAdded, with: { (snapshot) in
self.dataSnapshot = snapshot
if let dictionary = snapshot.value as? [String: Any]{
let comment = Comment(dictionary: dictionary)
self.comments.append(comment)
DispatchQueue.main.async {
self.tableView.reloadData()
self.handleKeyboardDidShow()
completion()
}
}
}, withCancel: nil)
}
func setUpKeyboardObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil)
}
#objc func handleKeyboardDidShow() {
if comments.count > 0 {
let indexPath = IndexPath(row: comments.count - 1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(ChatTableViewCell.self, forCellReuseIdentifier: reuseIdentifier)
tableView.register(ChatImageCell.self, forCellReuseIdentifier: chatImageIdentifier)
tableView.separatorStyle = .none
tableView.allowsSelection = false
tableView.backgroundColor = grayColor
tableView.keyboardDismissMode = .interactive
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(handleDismiss))
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
tableView.alwaysBounceVertical = true
}
#objc func handleDismiss() {
if let firebaseHandle = firebaseHandle {
self.commentRef.removeObserver(withHandle: firebaseHandle)
}
NotificationCenter.default.removeObserver(self)
self.dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let comment = comments[indexPath.row]
if comment.imageUrl != "" {
let cell = tableView.dequeueReusableCell(withIdentifier: chatImageIdentifier, for: indexPath) as! ChatImageCell
if comments.count != 0 {
cell.comment = comment
}
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! ChatTableViewCell
if comments.count != 0 {
cell.comment = comment
}
return cell
}
}
#objc func uploadImage() {
showImageActionSheet()
}
extension ChatTableViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
func showImageActionSheet() {
// declaring action sheet
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// declaring camera button
let camera = UIAlertAction(title: "Camera", style: .default) { (action) in
// if there is camera, then execute
if UIImagePickerController.isSourceTypeAvailable(.camera) {
self.showPicker(with: .camera)
}
}
// declaring library button
let library = UIAlertAction(title: "Library", style: .default) { (action) in
// if there is library, then execute
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
self.showPicker(with: .photoLibrary)
}
}
// declaring cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel)
// add action to the sheet
alertController.addAction(camera)
alertController.addAction(library)
alertController.addAction(cancel)
// present action sheet to the user
self.present(alertController, animated: true, completion: nil)
}
func showPicker(with source: UIImagePickerController.SourceType) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = source
self.present(picker, animated: true, completion: nil)
}
// fetch selected image from info with key
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedImage: UIImage?
// declaring editedImage
if let editedImage = info[.editedImage] as? UIImage {
selectedImage = editedImage
} else if let originalImage = info[.originalImage] as? UIImage {
selectedImage = originalImage
}
self.dismiss(animated: true, completion: nil)
FirebaseHelper.shared.uploadImage(image: selectedImage, firebaseRef: .comment_images, viewController: self) {
urlString in
let timeStamp = Helper.shared.dateOfCurrentTimeZone()
let childKey = FirebaseHelper.shared.getChildKey()
let profileImageUrlString: String
if let profileImageUrl = FirebaseHelper.shared.getPhotUrl() {
profileImageUrlString = profileImageUrl.absoluteString
} else {
profileImageUrlString = ""
}
let values: [String: Any] = ["text": "", "uid": self.uid, "timeStamp": timeStamp, "childkey": childKey, "username": self.username, "email": self.email ?? "", "imageUrl": urlString, "profileImageUrl": profileImageUrlString]
self.commentRef.child(childKey).updateChildValues(values, withCompletionBlock: { (error, dataRef) in
if error != nil {
Helper.shared.alertController(title: "Error", message: error!.localizedDescription, viewController: self)
return
}
})
}
}
}

swift save multiple images from collection view to firebase storage and get downloadURL?

enter image description herePlease help me I want to upload multiple image from my uicollectionview to firebase Storage and show downloadURL in Realtime database
i have try to search a lot but it no one work for me.
i can import the pictures from libray and make it show in myCollectionView but i don't know how to save it in to firebase.
Reports
-(userID)
-(reportID) - Using childByAutoId
- where i want to save to image
import UIKit
import Firebase
class ProblemViewController: UIViewController, UITextViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
var reportID : String!
var phonNumber : String!
var ref: DatabaseReference!
let storage = Storage.storage()
let userID = Auth.auth().currentUser!.uid
#IBOutlet weak var problemButton: UIButton!
#IBOutlet weak var myCollectionView: UICollectionView!
#IBOutlet weak var problemImage: UIImageView!
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.myCollectionView.delegate = self
self.myCollectionView.dataSource = self
retrieveUser()
generateReportID()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(importPicture))
}
#IBAction func sendProblemAction(_ sender: Any) {
//TODO: Storage image and Send information to Firebase and save it in our database
let imageName = UUID().uuidString
let storageRef = storage.reference().child("product_images/\(userID)/report/\(imageName).jpg")
if let uploadImage = problemImage.image!.jpegData(compressionQuality: 0.15) {
storageRef.putData(uploadImage, metadata: nil) { (metadata, error) in
if error != nil {
print("error")
return
}
storageRef.downloadURL(completion: {(url, error) in
if error != nil {
print(error!.localizedDescription)
return
}
let downloadURL = url?.absoluteString
let post = ["report_image_url": downloadURL!] as [String : Any]
self.registerUserIntoDatabase(userID: self.userID, values: post as [String : AnyObject])
})
}
}
self.navigationController?.popToRootViewController(animated: true)
}
private func registerUserIntoDatabase(userID: String, values: [String:AnyObject]){
//TODO: Send information to Firebase and save it in our database
ref = Database.database().reference()
let usersRef = ref.child("Reports").child("\(userID)/\(reportID!)")
usersRef.updateChildValues(values, withCompletionBlock: { (err, ref) in
})
}
func generateReportID () {
ref = Database.database().reference()
guard let key = self.ref.child("Reports").child("\(userID)/\(String(describing: reportID))").childByAutoId().key else { return }
reportID = key
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageView", for: indexPath)
if let imageView = cell.viewWithTag(1000) as? UIImageView {
imageView.image = images[indexPath.item]
}
return cell
}
#objc func importPicture() {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "picture", style: .default, handler: { (action) in
picker.sourceType = .photoLibrary
self.present(picker, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "cancel", style: .default, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
dismiss(animated: true)
images.insert(image, at: 0)
myCollectionView.reloadData()
print("key = \(image)")
}
}
I want to upload multiple images that show in uicollectionview to my firebase storage and show downloadURL in realtime database.
like this
Reports
-(userID)
-(reportID) - Using childByAutoId
- image1 : "https://firebasestorage.googleapis.com/..."
- image2 : "https://firebasestorage.googleapis.com/..."
- image3 : "https://firebasestorage.googleapis.com/..."
- image4 : "https://firebasestorage.googleapis.com/..."
My UICollection
When i press save it will error like this
My error

Adding Photos to Array and Displaying to UICollection View error

QUESTION
This code works to set an image to an array but comes up with the following error - 2017-12-06 12:31:21.264812+0000 SmartReceipts[880:172369] [discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}
I need to know what this means and if there is a possible fix around it?
import UIKit
class GalleryController: UICollectionViewController,
UIImagePickerControllerDelegate,
UINavigationControllerDelegate {
var Receipts = [UIImage?]()
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.reloadData()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Register cell classes
//self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
self.dismiss(animated: true, completion: nil)
print(info);
let newReceipts = info[UIImagePickerControllerEditedImage] as? UIImage
self.Receipts.append(newReceipts)
print("Array Contains \(self.Receipts.count) Receipts")
print(self.Receipts)
self.collectionView?.reloadData()
print("completedIfStatement")
}
#IBAction func getReceipts(_ sender: Any) {
print("PlusButtonPressed")
let optionMenu = UIAlertController(title: nil, message: "Choose Option", preferredStyle: .actionSheet)
// 2
let albumAction = UIAlertAction(title: "Album", style: .default, handler: {
(alert: UIAlertAction!) -> Void in
print("PhotosOption")
self.getFromReceipts()
})
let cameraAction = UIAlertAction(title: "Camera", style: .default, handler: {
(alert: UIAlertAction!) -> Void in
print("CameraOption")
self.getFromCamera()
})
//
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {
(alert: UIAlertAction!) -> Void in
print("Cancel")
})
// 4
optionMenu.addAction(albumAction)
optionMenu.addAction(cameraAction)
optionMenu.addAction(cancelAction)
// 5
self.present(optionMenu, animated: true, completion: nil)
}
func getFromReceipts() {
print("GetFromReceipts")
let cameraPicker = UIImagePickerController()
cameraPicker.delegate = self
cameraPicker.sourceType = .photoLibrary
self.present(cameraPicker, animated: true, completion: nil )
}
func getFromCamera() {
print("GetFromCamera")
let cameraPicker = UIImagePickerController()
cameraPicker.delegate = self
cameraPicker.sourceType = .camera
self.present(cameraPicker, animated: true, completion: nil )
}
//Number of Views
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.Receipts.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtindexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Receipts, for: indexPath as IndexPath) as? PhotoCell
cell?.imageView.image = self.Receipts[indexPath.row]
return cell!
}
}
The error maybe comes from not requesting the authorization to load an photo from the camera or the photo library. So you need to request for authorization before opening the camera like:
https://developer.apple.com/documentation/photos/phphotolibrary/1620736-requestauthorization
I guess you'r not requesting Photo/Camera authorizations.
You have to add the below keys to Info.plist.
Camera permission :
<key>NSCameraUsageDescription</key>
<string> ${PRODUCT_NAME} Camera Usage< </string>
For Photo Library, you will want this one to allow app user to browse the photo library.
<key>NSPhotoLibraryUsageDescription</key>
<string>${PRODUCT_NAME} Photo Usage</string>
And in you'r source code, to ask permission for the photo/camera you need to add this code (Swift 3):
PHPhotoLibrary.requestAuthorization({
(newStatus) in
if newStatus == PHAuthorizationStatus.authorized {
/* do stuff here */
}
})

Update a collection view in an other view

For school I have to make an iOS application. I would like to use an UICollectionView in an other View. I use the following code, but when I use self.libraryCollectionView.reloadData(), the collectionView function is not called. The CollectionView with the name libraryCollectionView should hold an gallery of Images.
Here you can see the code I wrote.
import UIKit
class CoverViewController: UIViewController, UICollectionViewDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UICollectionViewDataSource {
// MARK: Properties
#IBOutlet weak var photoImageView: UIImageView!
#IBOutlet weak var typeLabel: UILabel!
#IBOutlet weak var libraryCollectionView: UICollectionView!
var cover: Cover?
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
// Set up views if editing an existing Cover.
if let cover = cover {
photoImageView.image = cover.image
typeLabel.text = cover.type
}
libraryCollectionView.delegate = self
libraryCollectionView.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func addImage(_ sender: UIBarButtonItem) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet);
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePicker.sourceType = .camera
self.present(imagePicker, animated: true, completion: nil)
}
}))
alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action) in
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
imagePicker.sourceType = .photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// Methods for ImagePicker
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
images.append(pickedImage)
DispatchQueue.main.async{
self.libraryCollectionView.reloadData()
}
}
dismiss(animated: true, completion: nil)
}
// Methods for CollectionView
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 0
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellIdentifier = "cell"
let cell = libraryCollectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ImageCellView
NSLog(String(images.count))
cell.photoImageView.image = images[indexPath.row]
return cell
}
}
numberOfSections(in collectionView: UICollectionView) should return at least 1.
It's default value is also 1, so you can just delete the whole method from your code.