【问题标题】:image picker/UIImagePickerController show blank screen/NavigationController swift 5图像选择器/UIImagePickerController 显示空白屏幕/NavigationController swift 5
【发布时间】:2021-03-28 09:43:27
【问题描述】:

我试图从这个问题答案链接中得到答案但失败了:(

iOS UIImagePickerController showed blank page

然后我尝试下面的代码,但仍然显示没有图像列表的空白屏幕:( 我认为不要触发委托功能 您也可以从 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)
    }
}

添加此 info.plist
关键 =>>>> 隐私 - 照片库使用 value =>> 请访问图片库

控制台日志

  • 2020-12-17 22:49:11.928762+0600 image-picker-3[1309:51223] [生命周期] [u B37332A2-92E0-4D65-981B-0DBBDB4534D9:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] 连接插件 使用时中断。 2020-12-17 22:49:11.944027+0600 image-picker-3 [1309:51223] [生命周期] [u B37332A2-92E0-4D65-981B-0DBBDB4534D9:m(空)] [com.apple.mobileslideshow.photo-picker(1.0)] 连接插件 使用时失效。 2020-12-17 22:49:12.003410+0600 image-picker-3 [1309:51015] UIImagePickerController UIViewController 创建错误:Error Domain=NSCocoaErrorDomain Code=4099 "The 连接到名为 pid 0 的服务 com.apple.mobileslideshow.photo-picker.viewservice 被中断, 但是消息是通过一个额外的代理发送的,因此这个 代理已失效。" UserInfo={NSDebugDescription=The 连接到名为 pid 0 的服务 com.apple.mobileslideshow.photo-picker.viewservice 被中断, 但是消息是通过一个额外的代理发送的,因此这个 代理已失效。}

【问题讨论】:

    标签: ios swift xcode uiimagepickercontroller


    【解决方案1】:

    尝试按照下面我的编程示例,首先将您的按钮和委托添加到您的控制器并导入照片框架:

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

    现在在 viewDidLoad 添加按钮并设置约束:

    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
    }
    

    然后将你的 func 设置为显示图像选择器控制器:

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

    检查权限,别忘了设置你的info.plist隐私使用说明(和你一样):

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

    编写手动设置授权的函数:

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

    这是结果,在 dx 上手动授权的警报,在选择器控制器的左侧

    如果您没有看到预览照片,请尝试使用其他模拟器设备运行应用程序。

    【讨论】:

    • 我将它与 UIImagePickerController 一起使用。你知道我的错误在哪里@Fabio
    • @Ashfaqur_Rahman 用另一个模拟器设备运行你的(不是我的,而是你原来的)代码,如果结果相同,我认为你的代码中的错误是你没有实现授权请求案例(checkPermission () 函数) .... 有了这几个可用的元素,这是我唯一想到的...
    【解决方案2】:

    您可以通过将这些照片放入一个 collectionView 中来使用它,就像这样“我使用 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)
                }
            }
            
        }
    }
    

    }

    也可以正常使用:

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

    【讨论】:

    • 感谢您的回复。你建议我使用一个 pod 文件,即 Rxswift 效果很好,但我需要在 UIImagePickerController 中快速构建你知道我的错误在哪里吗@Menaim
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 2014-01-13
    相关资源
    最近更新 更多