Search code examples
swiftuibuttonuiimagephpickerviewcontroller

PHPickerViewController can't load selected image to UIButton


I created a UIButton programmatically Which can pick profile photo. So I made image picker with PHPicker, and it shows well.

But after I selected image, it doesn't show on the button.

I thought the original photos could be the problem. But it's the same with the newly downloaded photo except it sometimes shows white background or send real error phrase.

There is some warning on console like "Xxx(file directory)’ couldn’t be opened because there is no such file"

This PHPicker code worked well before, so I can't assume what is the problem. How can I select photo well?

    private let plusPhotoButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(named: "plus_photo"), for: .normal)
        button.tintColor = .white
        button.addTarget(self, action: #selector(imagePickerTapped), for: .touchUpInside)
        return button
    }()
    @objc func imagePickerTapped() {
        print("imagePickerTapped")
        var configuration = PHPickerConfiguration()
        configuration.selectionLimit = 1
        
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        self.present(picker, animated: true, completion: nil)
        
    }
// MARK: - PHPicker extention
extension RegistrationController : PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {

        picker.dismiss(animated: true)
        
        let itemProvider = results.first?.itemProvider
        
        if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
            itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
                DispatchQueue.main.async {
                    self.plusPhotoButton.layer.cornerRadius = self.plusPhotoButton.frame.width / 2
                    self.plusPhotoButton.layer.masksToBounds = true
                    self.plusPhotoButton.layer.borderColor = UIColor.black.cgColor
                    self.plusPhotoButton.layer.borderWidth = 2
                    self.plusPhotoButton.setImage(image as? UIImage, for: .normal)
                    
                }
            }
        } else {
            print("Image wasn't loaded!!!!")
        }
    }
}

I added frame setting for this button below

    view.addSubview(plusPhotoButton)
    plusPhotoButton.centerX(inView: view)
    plusPhotoButton.setDimensions(height: 140, width: 140)
    plusPhotoButton.anchor(top: view.safeAreaLayoutGuide.topAnchor, paddingTop: 32)
    
    let stack = UIStackView(arrangedSubviews: [emailTextField, passwordTextField, fullnameTextField, UsernameTextField, loginButton])
    stack.axis = .vertical
    stack.spacing = 20
    view.addSubview(stack)
    stack.anchor(top: plusPhotoButton.bottomAnchor, left: view.leftAnchor, right: view.rightAnchor, paddingTop: 32, paddingLeft: 32, paddingRight: 32)

'''


Solution

  • After reviewing your code you need make below changes in your code:

    Replace

    self.plusPhotoButton.setImage(image as? UIImage, for: .normal)
    

    with

    self.plusPhotoButton.setBackgroundImage(image as? UIImage, for: .normal)
    

    And you also need to remove image from button with:

    self.plusPhotoButton.setImage(nil, for: .normal)
    

    And here is your code with minor improvement:

    guard let img = image as? UIImage else { return }
    self.profileImage = img
    self.plusPhotoButton.layer.cornerRadius = self.plusPhotoButton.frame.width / 2
    self.plusPhotoButton.layer.masksToBounds = true
    self.plusPhotoButton.layer.borderColor = UIColor.black.cgColor
    self.plusPhotoButton.layer.borderWidth = 2
    self.plusPhotoButton.setBackgroundImage(img, for: .normal)
    self.plusPhotoButton.setImage(nil, for: .normal)