skip to Main Content

I am trying to get answer from this question answer link but failed 🙁

iOS UIImagePickerController showed blank page

Then I try below code but still show blank screen without image list 🙁
I think don’t fire the delegation function
You can also check from GitHub

https://github.com/MdAshfaqurRahmanIOS/image-picker-3

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!
    var imagePicker = UIImagePickerController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        imagePicker.delegate = self
    }
    @IBAction func buttonAction(_ sender: UIButton) {
        imagePicker.sourceType = .photoLibrary
        imagePicker.allowsEditing = true
        present(imagePicker, animated: true)
    }
}
extension ViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerEditedImage")] as? UIImage {
            imageView.image = image
        }
        picker.dismiss(animated: true, completion: nil)
    }
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
}

Add this info.plist
key =>>>> Privacy – Photo Library Usage
value =>> please access photogallery

Console log

  • 2020-12-17 22:49:11.928762+0600 image-picker-3[1309:51223] [lifecycle] [u B37332A2-92E0-4D65-981B-0DBBDB4534D9:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin
    interrupted while in use. 2020-12-17 22:49:11.944027+0600
    image-picker-3[1309:51223] [lifecycle] [u
    B37332A2-92E0-4D65-981B-0DBBDB4534D9:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin
    invalidated while in use. 2020-12-17 22:49:12.003410+0600
    image-picker-3[1309:51015] UIImagePickerController UIViewController
    create error: Error Domain=NSCocoaErrorDomain Code=4099 "The
    connection to service on pid 0 named
    com.apple.mobileslideshow.photo-picker.viewservice was interrupted,
    but the message was sent over an additional proxy and therefore this
    proxy has become invalid." UserInfo={NSDebugDescription=The
    connection to service on pid 0 named
    com.apple.mobileslideshow.photo-picker.viewservice was interrupted,
    but the message was sent over an additional proxy and therefore this
    proxy has become invalid.}

enter image description here
enter image description here
enter image description here
enter image description here

2

Answers


  1. You can use it by taking these photos into a collectionView like this "I’ve made it using RxSwift:

    import UIKit
    import RxSwift
    import Foundation
    import Photos
    
    private let reuseIdentifier = "ImageCell"
    
    class ImagesCollectionViewController: UICollectionViewController {
        
    //MARK: - vars
    private var images = [PHAsset]()
    private var selectedPhotoSubject = PublishSubject<UIImage>()
    var selectedPhoto: Observable<UIImage> {
        return selectedPhotoSubject.asObservable()
    }
    
    //MARK: - LifeCycle
    override func viewDidLoad() {
        super.viewDidLoad()
        linkPhotosLibrary()
        self.title = "Pick an Image"
        
    }
    //MARK: - PhotoLibrary
    private func linkPhotosLibrary() {
        PHPhotoLibrary.requestAuthorization { [weak self] status in
            if status == .authorized {
                
                let assets = PHAsset.fetchAssets(with: PHAssetMediaType.image,options: nil)
                assets.enumerateObjects { (object, count, stop) in
                    self?.images.append(object)
                }
                self?.images.reverse()
                DispatchQueue.main.async {
                self?.collectionView.reloadData()
                }
            }
            
        }
    }
    
    // MARK: - UICollectionViewDataSource
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return images.count
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCell
        
        let asset = images[indexPath.row]
        let manager = PHImageManager.default()
        
        manager.requestImage(for: asset, targetSize: CGSize(width: 200,height: 200), contentMode: .aspectFit, options: nil) { image, _ in
            
            DispatchQueue.main.async {
                cell.imageViewOutlet.image = image
            }
        }
        
        return cell
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        let selectedAsset = images[indexPath.row]
        PHImageManager.default().requestImage(for: selectedAsset, targetSize: CGSize(width: 500, height: 500), contentMode: .aspectFit, options: nil) { [weak self] image , info in
            guard let info = info else {return}
            let isDegradedImage = info["PHImageResultIsDegradedKey"] as! Bool
            // as we will call this function 2 times one for the small image in the collection and one here that's why we use it as this will tell us if the image is thumbnail or original image
            if !isDegradedImage {
                
                if let image = image {
                    self?.selectedPhotoSubject.onNext(image)
                    self?.dismiss(animated: true, completion: nil)
                }
            }
            
        }
    }
    

    }

    or you can use it normally:

        var myGallery: GalleryController!
    
        func showGalleryImages () {
            
            self.myGallery = GalleryController()
            self.myGallery.delegate = self
            Config.tabsToShow = [.imageTab, .cameraTab]
            Config.Camera.imageLimit = 100
            
            self.present(self.myGallery, animated: true, completion: nil)
            
        }
        
    }
    
    Login or Signup to reply.
  2. Try to follow my programmatically example below, first add your button and delegates to your controller and import Photo framework:

    import UIKit
    import Photos
    
    class YourViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    lazy var takePicButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = .red
        button.setTitle("Present img picker", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 16, weight: .semibold)
        button.layer.cornerRadius = 14
        button.clipsToBounds = true
        button.addTarget(self, action: #selector(handlepickPicture), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        
        return button
    }()
    

    now in viewDidLoad add button and set constraints:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(takePicButton)
        takePicButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
        takePicButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
        takePicButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true
        takePicButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }
    

    After that set your func to present image picker controller:

    var imagePicker = UIImagePickerController()
    
    @objc fileprivate func handlepickPicture() {
        
        imagePicker.delegate = self
        imagePicker.sourceType = .photoLibrary
        imagePicker.view.tintColor = .white
        imagePicker.mediaTypes = ["public.image"]
        imagePicker.allowsEditing = true
        imagePicker.navigationBar.barTintColor = .black
        
        checkPermission()
    }
    

    check the permission, don’t forget to set your info.plist privacy usage description (like you):

    fileprivate func checkPermission() {
        let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
        switch photoAuthorizationStatus {
        case .authorized:
            print("Add Photo")
            if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum){
                print("Access is granted by user")
                self.present(imagePicker, animated: true, completion: nil)
            }
            print("Access is granted by user")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization({
                (newStatus) in
                print("status is (newStatus)")
                if newStatus ==  PHAuthorizationStatus.authorized {
                    /* do stuff here */
                    DispatchQueue.main.async {
                        self.present(self.imagePicker, animated: true, completion: nil)
                    }
                    print("success")
                }
            })
            print("It is not determined until now")
        case .restricted:
            // same same
            print("User do not have access to photo album.")
            goToSetting()
        case .denied:
            // same same
            print("Text tapped...")
            goToSetting()
            print("User has denied the permission.")
        case .limited:
            goToSetting() // the function show an alert to enable Authorization manually
            print("User has denied the permission.")
        @unknown default:
            fatalError()
        }
    }
    

    write the function to set authorization manually:

    fileprivate func goToSetting() {
        let title = "Oooooops!"
        let message = "Hi man, for use this App press Go To settings and enabled access to Pohto Gallery... Check read and write option and relaunch the App!"
        
        let alertController = UIAlertController(title: "", message: "", preferredStyle: .alert)
        
        let subview = (alertController.view.subviews.first?.subviews.first?.subviews.first!)! as UIView
        subview.backgroundColor = UIColor(white: 0, alpha: 0.2)
        
        alertController.setValue(NSAttributedString(string: title, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 18, weight: .heavy),NSAttributedString.Key.foregroundColor : UIColor.red]), forKey: "attributedTitle")
        alertController.setValue(NSAttributedString(string: message, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 14, weight: .regular),NSAttributedString.Key.foregroundColor : UIColor.white]), forKey: "attributedMessage")
        
        let cancelAction = UIAlertAction(title: "Cancel", style: .destructive) { (_) in
            print("Action cancelled")
        }
        
        let goToSettingPermission = UIAlertAction(title: "Go To setting", style: .default) { (action) in
            UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
        }
        
        alertController.addAction(goToSettingPermission)
        alertController.addAction(cancelAction)
        
        self.present(alertController, animated: true, completion: {
        })
    }
    

    this is the result, on dx the alert for manual authorization, on left the picker controller

    enter image description here

    If you don’t see the preview photos, try to run app with another simulator device.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search