UIImagePickerController 从 UICollectionViewCell 内的 UIImageView 呈现

Posted

技术标签:

【中文标题】UIImagePickerController 从 UICollectionViewCell 内的 UIImageView 呈现【英文标题】:UIImagePickerController presented from UIImageView inside UICollectionViewCell 【发布时间】:2017-08-14 23:00:40 【问题描述】:

我在从 UIImageView 中的 UIImagePickerController 加载选定图像时遇到问题。 UIImageView 通过点击 collectionViewCell 中的按钮呈现。在 collectionViewCell 中点击该按钮时,UIImageView 会以动画形式显示在视图中。在点击该 UIImageView 时,会显示 uiimagepicker。选择图像时,选择器会很好地关闭,但图像不会在选择器关闭时加载到 uiimageView 内(占位符图像仍然存在并且不会被所选图像替换)。我的控制台中没有发生崩溃或错误。感谢您的帮助!

UICollectionViewCell 类 - LoginCell

class LoginCell: UICollectionViewCell, UIImagePickerControllerDelegate, UINavigationControllerDelegate 

lazy var createUsernameButton: UIButton = 
    let customButton = UIButton(type: .system)
    customButton.setTitle("Create Username", for: .normal)
    customButton.addTarget(self, action: #selector(animateIn), for: .touchUpInside)
    return customButton
()

func animateIn() 
    addSubview(profileImageView)

    profileImageView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
    profileImageView.alpha = 0

    UIView.animate(withDuration: 0.2) 
        self.profileImageView.alpha = 1
        self.profileImageView.transform = CGAffineTransform.identity
    



    lazy var profileImageView: UIImageView = 
        let imageView = UIImageView()
        imageView.image = UIImage(named: "avatar-bg-2x")
        imageView.addGestureRecognizer(UITapGestureRecognizer(target:self, action: #selector(handleSelectProfileImage)))
        imageView.isUserInteractionEnabled = true
        return imageView
    ()

    var loginController: LoginController?

    func handleSelectProfileImage() 
        guard let loginController = delegate as? LoginController else 
            return
        
        loginController.showImagePicker()
    

//.....

loginController

class LoginController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, LoginControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate 

    weak var loginCollectionView: UICollectionView!
    var loginCell: LoginCell?

    func showImagePicker() 
        let picker = UIImagePickerController()
        picker.delegate = self
        picker.allowsEditing = true
        present(picker, animated: true, completion: nil)
    

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 

        var selectedImageFromImagePicker: UIImage?

        if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage 
            selectedImageFromImagePicker = editedImage
         else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage 
            selectedImageFromImagePicker = originalImage
        

        dismiss(animated: true, completion: 
            if let selectedImage = selectedImageFromImagePicker 
                self.loginCell?.profileImageView.image = selectedImage
                print("was dismissed")
            
        )
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
            let loginCell = collectionView.dequeueReusableCell(withReuseIdentifier: loginCellId, for: indexPath) as! LoginCell
            loginCell.delegate = self
            return loginCell
    
// ...

【问题讨论】:

您确认selectedImageFromImagePicker 是正确的吗?看起来它的编码可能是nil 我相信它没有返回 nil(一个值显示在控制台中,用于 selectedImageFromPicker)。当我使用它将选定的图像传递给标准 viewController 中的 UIImageView 时,同样的代码也可以正常工作。与这种情况的不同之处在于 profileImageView 呈现在 collectionViewCell(不是标准的 viewController)中。 【参考方案1】:

我发现了问题,你没有在主线程上更新图像。试试这个:

1.更改登录控制器类中的代码以匹配以下代码。

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 

    var selectedImageFromImagePicker: UIImage?

    if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage 
        selectedImageFromImagePicker = editedImage
     else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage 
        selectedImageFromImagePicker = originalImage
    

    if let selectedImage = selectedImageFromImagePicker 
        DispatchQueue.main.async 
            self.loginCell?.profileImageView.image = selectedImage
            self.loginCollectionView.reloadData() //EDIT: add this new piece of code
        
    

    dismiss(animated: true, completion: nil)


var profileImage: UIImage?

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let loginCell = collectionView.dequeueReusableCell(withReuseIdentifier: loginCellId, for: indexPath) as! LoginCell
        loginCell.delegate = self
        loginCell.profileImageView.image = profileImage != nil ? profileImage : UIImage(named: "avatar-bg-2x")
        return loginCell

2.在您的 loginCell 类中更改此代码以匹配以下代码。

lazy var profileImageView: UIImageView = 
    let imageView = UIImageView()
    //removed line here
    imageView.addGestureRecognizer(UITapGestureRecognizer(target:self, action: #selector(handleSelectProfileImage)))
    imageView.isUserInteractionEnabled = true
    return imageView
()

【讨论】:

好的,谢谢。您的逻辑和主线程绝对有意义,但仍然无法正常工作。我更新了我的原始帖子,以显示可能缺少的内容,以便更清楚地了解我的结果。我想知道它是否与我的 UIImageView 的呈现方式有关......在我的情况下,我通过 animateIn() 函数将 UIImageView 呈现在 collectionViewCell 的顶部。不确定这是否会导致问题...? 我实际上也考虑过更新...仍然无法正常工作,并且该更新得到“致命错误:在展开可选值时意外发现 nil”。 您的逻辑完全合理并且越来越接近,但仍然无法正常工作并给出相同的致命错误.... hmmmmm ? 我只是重新编写了将 UIImageView 呈现在新的 viewcontroller 类中而不是在 collectionViewCell 顶部的 uiview 中呈现的逻辑。这是目前完成我需要的工作。不过,感谢您的见解和时间!

以上是关于UIImagePickerController 从 UICollectionViewCell 内的 UIImageView 呈现的主要内容,如果未能解决你的问题,请参考以下文章

从 UITabBarController 驱动 UIImagePickerController

从 UIImagePickerController 保存视频

UIImagePickerController 从 UICollectionViewCell 内的 UIImageView 呈现

如何从 UIImagePickerController 获取图像文件名

从 UIImagePickerController 获取图像位置

从 UIImagePickerController 传递图像数据以进行后台处理