Image dispatcher delegate in separate class not working

I am new to Xcode and Swift. I am currently playing with Start iOS App Development (Swift) from Apple.

Everything works fine so far except for one. The tutorial handles the Image Picker delegate inside the main class ViewController

, making it protocol-compliant UIImagePickerControllerDelegate

and UINavigationControllerDelegate

. I wanted to try something else and move the delegate into a separate class. Here's what I did:

import UIKit
import Foundation

class MealPhotoDelegate: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    var placeholder: UIImageView?

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
            fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
        }

        placeholder!.image = selectedImage

        dismiss(animated: true, completion: nil)
    }
}

      

And in ViewController

:

@IBAction func selectImageFromPhotoLibrary(_ sender: UITapGestureRecognizer) {
    nameTextField.resignFirstResponder()

    let imagePickerController = UIImagePickerController()
    imagePickerController.sourceType = .photoLibrary

    let imagePickerDelegate = MealPhotoDelegate()
    imagePickerDelegate.placeholder = photoImageView

    imagePickerController.delegate = imagePickerDelegate

    present(imagePickerController, animated: true, completion: nil)
}

      

Every time the Image Picker appears and when I view the photos, an error is generated:

2017-07-20 01: 49: 00.937470 + 0200 FoodTracker [41600: 4236501] API error: (null) returns 0 width, assuming UIViewNoIntrinsicMetric

What am I doing wrong? Is it a UIViewController

good choice of superclass for a delegate? It seems to me that no.

+2


source to share


1 answer


Your problem is memory management. Inside selectImageFromPhotoLibrary

create a local instance MealPhotoDelegate

. At the end of the method, this instance is out of scope and deallocated because there is no strong reference to it. So the image collector delegate becomes nil

and it doesn't work.

The solution is to link to an instance MealPhotoDelegate

. This can be easily done using a property in the view controller class.

Add the following property to the view controller class:

var imagePickerDelegate: MealPhotoDelegate?

      

Then update the line:

let imagePickerDelegate = MealPhotoDelegate()

      



from:

imagePickerDelegate = MealPhotoDelegate()

      

What is it. It will now work.

As a side note, there is no reason yours MealPhotoDelegate

should expand UIViewController

. Make an extension instead NSObject

. And you fix new problems using the correct code.

This is how it should be:

class MealPhotoDelegate: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    var placeholder: UIImageView?

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
            fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
        }

        if let placeholder = placeholder {
            placeholder.image = selectedImage
        }

        picker.dismiss(animated: true, completion: nil)
    }
}

      

+2


source







All Articles