Search code examples
iosswiftuistoryboardsegueuicontainerview

Add a photo, and reload embedded photo container view controller


I've a view controller that collects information including the ability to add multiple photos to a record. As each photo is added, the new photo appears as the feature photo (a storyboard UIImageview inside the VC). Each photo should also be added to an array of images, which is then passed to a container view with its own custom view controller, and shown. As each photo is added, the feature photo is shown, but the container does not reload with the images.

The photo container does appear to work when an array of existing photos is passed in via a prepare for segue method like so:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    if (segue.identifier == "segueToPhotoCollection")
    {
        if let imagesArray = images
        {
            print("photos prepared")
            let controller =  (segue.destinationViewController as! PhotoCollectionVC)
            controller.images = imagesArray
            controller.delegate = self
        }
    }

And if there are no photos, the container still loads (and prints "container loaded, but no photos").

class PhotoCollectionVC: UICollectionViewController
{
var images: [UIImage]?

weak var delegate: FeatureImageController?

override func viewDidLoad()
{
    super.viewDidLoad()

    if images?.count > 0
    { print("container loaded with photos: \(images!.count)") }
    else { print ("container loaded, but no photos") }

What I need is somehow to either recall the prepareForSegue method or find another way to update and reload the container once an image is added. The picker didFinishPickingMediaWithInfo looks like:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
    picker.dismissViewControllerAnimated(true, completion:
    {
        var imageTaken = info[UIImagePickerControllerEditedImage] as? UIImage
        ...

        if let imageTakenNotNil = imageTaken
        {
            if self.images == nil
            { self.images = [] }
            self.images?.append(imageTakenNotNil)

And then a line that will somehow re-pass that array of images to the container. Do I need a delegate method to do this?!?


Solution

  • In your main view controller, add a variable that will maintain a reference to your embedded view controller. In prepareForSegue, assign this reference. Then in didFinishPickingMediaWithInfo you can use this reference to make changes in your embedded view controller and refresh it.

    So just under your IBOutlets you'll have something like:

    var photoControlView: PhotoCollectionVC?
    

    Your prepareForSegue will be like:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    {
        if (segue.identifier == "segueToPhotoCollection")
        {
            if let imagesArray = images
            {
                print("photos prepared")
                let controller =  (segue.destinationViewController as! PhotoCollectionVC)
                controller.images = imagesArray
                controller.delegate = self
                self.photoControlView = controller
            }
        }
    

    And in didFinishPickingMediaWithInfo you can now do:

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
    {
        picker.dismissViewControllerAnimated(true, completion:
        {
            var imageTaken = info[UIImagePickerControllerEditedImage] as? UIImage
            ...
    
            if let imageTakenNotNil = imageTaken
            {
                if self.images == nil
                { self.images = [] }
                self.images?.append(imageTakenNotNil)
                self.photoControlView!.images = self.images
                self.photoControlView!.reloadData()
                self.photoControlView!.setNeedsDisplay()
    

    I'm not sure if the setNeedsDisplay() call is necessary or even correct to refresh the view, but I have used the rest of this method before and know it works.