Accessing the camera and photo library in swift 4
Here is the code to load image from photos & camera in iOS.
⁃ You need to create an outlet of your UIImageView
⁃ Then add a tap gesture on to image view
⁃ Then connect tap gesture with the didTapOnImageView function.
⁃ Then add the following extension to your view controller.
//MARK:- Image Picker
extension YourViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
//This is the tap gesture added on my UIImageView.
@IBAction func didTapOnImageView(sender: UITapGestureRecognizer) {
//call Alert function
self.showAlert()
}
//Show alert to selected the media source type.
private func showAlert() {
let alert = UIAlertController(title: "Image Selection", message: "From where you want to pick this image?", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action: UIAlertAction) in
self.getImage(fromSourceType: .camera)
}))
alert.addAction(UIAlertAction(title: "Photo Album", style: .default, handler: {(action: UIAlertAction) in
self.getImage(fromSourceType: .photoLibrary)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: nil))
self.present(alert, animated: true, completion: nil)
}
//get image from source type
private func getImage(fromSourceType sourceType: UIImagePickerController.SourceType) {
//Check is source type available
if UIImagePickerController.isSourceTypeAvailable(sourceType) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = sourceType
self.present(imagePickerController, animated: true, completion: nil)
}
}
//MARK:- UIImagePickerViewDelegate.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
self.dismiss(animated: true) { [weak self] in
guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
//Setting image to your image view
self?.profileImgView.image = image
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
Note: Don't forget to add the privacy settings in info.plist
Privacy - Camera Usage Description
Privacy - Photo Library Usage Description
I can access iOS Photo Library without requesting permission
As per UIImagePickerController
behaviour, It never gives dialogue to the user for Photos
access. UIImagePickerController
only ask for the Camera
permission.
You have to ask for Photos
permission
manually to the user. By using the below code you can ask the user for Photos
permission.
import Photos
@IBAction func allowAccessToPhotos(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Photo Source", message: "Choose a Source", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action:UIAlertAction) in imagePickerController.sourceType = .photoLibrary
let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
switch photoAuthorizationStatus {
case .authorized:
self.present(imagePickerController, animated: true, completion: nil)
case .notDetermined:
PHPhotoLibrary.requestAuthorization({
(newStatus) in
DispatchQueue.main.async {
if newStatus == PHAuthorizationStatus.authorized {
self.present(imagePickerController, animated: true, completion: nil)
}else{
print("User denied")
}
}})
break
case .restricted:
print("restricted")
break
case .denied:
print("denied")
break
}}))
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction) in imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
}))
}
Please refer reference.
Important Note:
If you're not asking for
Photos
permission to the user then It will cause rejection by the apple team. It depends on your luck, Sometimes the apple team ignore it and sometimes reject our app.
Swift Ask for user’s permission to access the photo library
i just add the key NSPhotoLibraryUsageDescription
in Project/info/Custom IOS Target Properties . instead of info.plist
and now it's working fine
Request Permission for Camera and Library in iOS 10 - Info.plist
You have to add the below permission in Info.plist. More Referance
Camera :
Key : Privacy - Camera Usage Description
Value : $(PRODUCT_NAME) camera use
Photo :
Key : Privacy - Photo Library Usage Description
Value : $(PRODUCT_NAME) photo use
Determine if the access to photo library is set or not - PHPhotoLibrary
Check +[PHPhotoLibrary authorizationStatus]
– if not set, it will return PHAuthorizationStatusNotDetermined
. (You can then request access using +requestAuthorization:
on the same class.)
Swift Photo Library Access
It is not so simple but as mentioned by Rob you can save the photo asset url and later fetch it using the Photos framework. You can fetch them using PHImageManager method requestImageData.
import UIKit
import Photos
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@IBOutlet weak var imageView: UIImageView!
let galleryPicker = UIImagePickerController()
// create a method to fetch your photo asset and return an UIImage on completion
override func viewDidLoad() {
super.viewDidLoad()
// lets add a selector to when the user taps the image
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(openPicker)))
// request authorization
switch PHPhotoLibrary.authorizationStatus() {
case .authorized:
print("The user has explicitly granted your app access to the photo library.")
return
case .denied:
print("The user has explicitly denied your app access to the photo library.")
case .notDetermined:
PHPhotoLibrary.requestAuthorization { status in
print("status", status)
}
case .restricted:
print("Your app is not authorized to access the photo library, and the user cannot grant such permission.")
default: break
}
}
// opens the image picker for photo library
@objc func openPicker(_ gesture: UITapGestureRecognizer) {
galleryPicker.sourceType = .photoLibrary
galleryPicker.delegate = self
present(galleryPicker, animated: true)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.imageView.contentMode = .scaleAspectFit
// check if there is an url saved in the user defaults
// and fetch its first object (PHAsset)
if let assetURL = UserDefaults.standard.url(forKey: "assetURL") {
if let asset = PHAsset.fetchAssets(withALAssetURLs: [assetURL], options: nil).firstObject {
asset.asyncImageData { data, _, _, _ in
print("fetched")
guard let data = data else { return }
self.imageView.image = UIImage(data: data)
}
} else {
print("assetURL:", assetURL)
self.imageView.image = UIImage(contentsOfFile: assetURL.path)
}
} else {
print("no assetURL found")
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
print("canceled")
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
self.imageView.image = info[.originalImage] as? UIImage
if let phAsset = info[.phAsset] as? PHAsset {
phAsset.asyncURL { url in
guard let url = url else { return }
UserDefaults.standard.set(url, forKey: "assetURL")
print("assetURL saved")
}
}
dismiss(animated: true)
}
}
extension PHAsset {
func asyncURL(_ completion: @escaping ((URL?) -> Void)) {
switch mediaType {
case .image:
let options: PHContentEditingInputRequestOptions = .init()
options.canHandleAdjustmentData = { _ in true }
requestContentEditingInput(with: options) { editingInput, _ in
completion(editingInput?.fullSizeImageURL)
}
case .video:
let options: PHVideoRequestOptions = .init()
options.version = .original
PHImageManager.default()
.requestAVAsset(forVideo: self, options: options) { asset, _, _ in
completion((asset as? AVURLAsset)?.url)
}
default:
completion(nil)
}
}
func asyncImageData(version: PHImageRequestOptionsVersion = .original, completion: @escaping (Data?, String?, UIImage.Orientation, [AnyHashable : Any]?) -> ()) {
let options = PHImageRequestOptions()
options.version = version
PHImageManager.default()
.requestImageData(for: self, options: options, resultHandler: completion)
}
}
extension URL {
var phAsset: PHAsset? {
PHAsset.fetchAssets(withALAssetURLs: [self], options: nil).firstObject
}
}
Note: Don't forget to edit your info plist and add "Privacy - Photo Library Usage Description"
Sample
No permission to pick a photo from the photo library
The issue is that my users are able to access the photo library without getting a request alert to access their photo library
That is not an "issue". That is correct behavior.
The UIImagePickerController (or, in iOS 14, the PHPickerViewController) does not require user authorization for the photo library. That's because your app is not accessing the photo library! The runtime is accessing it, and the user is willingly handing you a photo. You receive the photo, not as a full-fledged photo in the library — that would be a PHAsset — but as a mere UIImage. So all you are getting is disembodied images.
If you wanted to turn around and fetch the PHAsset and look into the library, you would need user authorization. But you are just asking for the .editedImage
, so you don't need user authorization.
If the .editedImage
is nil
, that's because it's the wrong key; if the user didn't edit the image, what you want is the .originalImage
. And you still won't need authorization.
If you want to ask the system to present the alert that requests authorization, go ahead and ask it to do that. But the user won't get the alert by magic merely because you use the picker.
Related Topics
Setting Up Uiscrollview to Swipe Between 3 View Controllers
Custom Repeat Interval for Uilocalnotification
An Elegant Way to Ignore Any Errors Thrown by a Method
Press-And-Hold Button for "Repeat Fire"
Ios13 Share Sheet: How to Set Preview Thumbnail When Sharing Uiimage
Enable/Disable Apple Push Notification from iPhone App
Leak from Nsurl and Avaudioplayer Using Arc
How to Build Boost-Libraries for Iphone
Make Uicollectionview Zoomable
iOS 11 Layout Guidance About Safe Area for iPhone X
Selecting a Word in a Uitextview
Can't Submit Apps to Appstore: Error Itms-90534: "Invalid Toolchain
How to Create a Uiimage from the Current Graphics Context
Get Pixel Value from Cvpixelbufferref in Swift
Could Not Cast Value of Type 'Uitableviewcell' to '(Appname).(Customcellname)'
What Do the "M" and "A" Icons in the Project Navigator of Xcode 4 Mean When I Create a New Project