Agung
Agung

Reputation: 13883

why my Image doesn't appear in UIImage View?

I made a view controller to show up an Image, the image will be shown up after the user press the right button item in the checkOutVC like this

enter image description here

the image should be appear in the ReusableImageDisplayVC like this

enter image description here

I send the image from checkOutVC to ReusableImageDisplayVC, the code I use for those view controller are below :

class CheckoutTVC: UITableViewController {

 @IBAction func openImageBarButtonDidPressed(_ sender: Any) {

        var displayedImage = UIImage()
        let imagePath = "https://***.jpg"
        let urlImage = URL(string: imagePath)

        NetworkingService.fetchData(url: urlImage!) { (result) in
            self.activityIndicator.startAnimating()

            switch result {
            case .failure(let error) :
                self.activityIndicator.stopAnimating()
                self.showAlert(alertTitle: "Sorry", alertMessage: error.localizedDescription, actionTitle: "Back")
            case .success (let imageData):
                self.activityIndicator.stopAnimating()
                displayedImage = UIImage(data: imageData)!
            }
        }


        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let popup = storyboard.instantiateViewController(withIdentifier: "imageDisplay") as! ReusableImageDisplayVC
        popup.photo = displayedImage


        present(popup, animated: true, completion: nil)

    }
}

and the code in ReusableImageDisplayVC are below

class ReusableImageDisplayVC: UIViewController {

    @IBOutlet weak var ImagePhoto: UIImageView!
    var photo : UIImage?

    override func viewDidLoad() {
        super.viewDidLoad()

        if photo == nil {
            print("photo is nil")
        } else {
            print("photo is not nil")
        }

        print(photo!)

        ImagePhoto.image = photo!


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ReusableImageDisplayVC.tapFunction(sender:)))
        tapGesture.numberOfTapsRequired = 1
        ImagePhoto.addGestureRecognizer(tapGesture)
        view.addGestureRecognizer(tapGesture)

    }



    @objc func tapFunction(sender: UITapGestureRecognizer) {
        dismiss(animated: true, completion: nil)
    }


}

as we can see in the ReusableImageDisplayVC I am trying to make sure that the UIImage from previous VC is available, and in the debugging area it is printed

photo is not nil, UIImage: 0x6040008bde20, {0, 0}

I have also assigned to the ImageView ImagePhoto.image = photo!

but why when I run the app, it doesn't appear?

but if I hard code the downloading image process stright in the ReusableImageDisplayVC like the code below, the image will appear

class ReusableImageDisplayVC: UIViewController {

    @IBOutlet weak var ImagePhoto: UIImageView!
    var photo : UIImage?
    var something : String?

    override func viewDidLoad() {
        super.viewDidLoad()

        let imagePath = "https://***.jpg"
        let urlImage = URL(string: imagePath)

        NetworkingService.fetchData(url: urlImage!) { (result) in

            switch result {
            case .failure(let error) :
                self.showAlert(alertTitle: "Sorry", alertMessage: error.localizedDescription, actionTitle: "Back")
            case .success (let imageData):
               self.ImagePhoto.image = UIImage(data: imageData)!
            }
        }


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ReusableImageDisplayVC.tapFunction(sender:)))
        tapGesture.numberOfTapsRequired = 1
        ImagePhoto.addGestureRecognizer(tapGesture)
        view.addGestureRecognizer(tapGesture)

    }



    @objc func tapFunction(sender: UITapGestureRecognizer) {
        dismiss(animated: true, completion: nil)
    }


}

what went wrong in here?

Upvotes: 1

Views: 182

Answers (1)

Jake
Jake

Reputation: 13771

displayedImage isn't set yet when you present the ReusableImageDisplayVC view controller. This is because you're presenting the view controller before the async call is finished. Try this instead:

@IBAction func openImageBarButtonDidPressed(_ sender: Any) {
    NetworkingService.fetchData(url: urlImage!) { [weak self] (result) in
        var displayedImage = UIImage()
        let imagePath = "https://example.com/someimage.jpg"
        let urlImage = URL(string: imagePath)

        self?.activityIndicator.startAnimating()

        switch result {
        case .failure(let error) :
            self?.activityIndicator.stopAnimating()
            self?.showAlert(alertTitle: "Sorry", alertMessage: error.localizedDescription, actionTitle: "Back")
            return //return instead of presenting ReusableImageDisplayVC 
        case .success (let imageData):
            self?.activityIndicator.stopAnimating()
            displayedImage = UIImage(data: imageData)!
        }

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let popup = storyboard.instantiateViewController(withIdentifier: "imageDisplay") as! ReusableImageDisplayVC
        popup.photo = displayedImage

        self?.present(popup, animated: true, completion: nil)
    }
}

(note the use of [weak self], self?, and return in the fetchData completion handler)

Upvotes: 3

Related Questions