Get an Image data from one view controller to the second

Hello, I have had success submitting string data from one view controller to the next. Images don’t seem to be working. I get error like “it was found nil while unwrapping it”. Do you know of a good way to do this?

How are you passing your string data?

Can you describe it or provide code?

You can pass an image in the same way

Paste your code in as text, rather than providing a screenshot.

To format the code nicely, place 3 back-ticks ``` on the line above your code and 3 back-ticks ``` on the line below your code. The 3 back-ticks must be the ONLY characters on the line. The back-tick character is located on the same keyboard key as the tilde character ~ (which is located below the Esc key). You can also highlight an entire code block and click the </> button on the toolbar to wrap the block for you.

This also makes it easier for anyone assisting as they can copy the code and carry out some testing.

2 Likes

Hey Mikaelacaron,

Thanks for replying. Here it is:

This is part of the first view controller:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

       if indexPath.row >= 0 {
           if let vc = storyboard?.instantiateViewController(identifier: "messageVC") as? MessageViewController {
               
               //  *** Networking *** Loop through images urls in Firebase  *** Networking ***
               guard let uid = messenger?.documents[indexPath.row].fields.thumbnail.stringValue else {return}
               let Ref = Storage.storage().reference(forURL: "gs://myprojectnamegoeshere.appspot.com/\(uid)")
               Ref.getData(maxSize: 1 * 1024 * 1024) { data, error in
                       if error != nil {
                           print((error!.localizedDescription))
                       } else {
                           
                               DispatchQueue.main.async {
                                   //cellImg.image =  UIImage(data: data!)
                                   vc.imgPosted = UIImage(contentsOfFile: uid)!

                               }
                
                       }
                   }
               
               
               vc.subjectPosted = (messenger?.documents[indexPath.row].fields.date.stringValue)!
               vc.subjectPosted = (messenger?.documents[indexPath.row].fields.subject.stringValue)!
               vc.bodyPosted = (messenger?.documents[indexPath.row].fields.body.stringValue)!
               
               navigationController?.pushViewController(vc, animated: true)
              
               
           }
           
       }

Here is the second view controller:

import FirebaseAuth
import FirebaseDatabase
import FirebaseFirestore
import FirebaseStorage
import SideMenu
import UIKit

class MessageViewController: UIViewController {
    
    // private var inboxViewController = InboxViewController()
    @IBOutlet weak var thumbnailMsg: UIImageView!
    @IBOutlet weak var dateMsg: UILabel!
    @IBOutlet weak var subjectMsg: UILabel!
    @IBOutlet weak var bodyMsg: UITextView!
    
    // Global variables for recieving data from InboxViewController
    var imgPosted = UIImage()
    var datePosted = ""
    var subjectPosted = ""
    var bodyPosted = ""
    
    
    var messenger: Messenger?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Recieve data from InboxViewController
        thumbnailMsg.image =  imgPosted.imageWithoutBaseline()
        dateMsg.text = datePosted
        subjectMsg.text = subjectPosted
        bodyMsg.text = bodyPosted

    }

    @IBAction func backToInbox(_ sender: Any) {
        let vc = UIStoryboard(name: "Main", bundle: nil)
        let controller = vc.instantiateViewController(identifier: "inbox") as! InboxViewController
        
        navigationController?.pushViewController(controller, animated: true)
        
  
        
    }
    
    
    
}

I believe what I am facing is a networking issue. The image load’s fine when in is local be when it is coming from Firebase I get this:

I how do I fix this?

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

       if indexPath.row >= 0 {
           if let vc = storyboard?.instantiateViewController(identifier: "messageVC") as? MessageViewController {
               
               vc.imgPosted = UIImage(contentsOfFile: (messenger?.documents[indexPath.row].fields.thumbnail.stringValue)!)!
               vc.subjectPosted = (messenger?.documents[indexPath.row].fields.date.stringValue)!
               vc.subjectPosted = (messenger?.documents[indexPath.row].fields.subject.stringValue)!
               vc.bodyPosted = (messenger?.documents[indexPath.row].fields.body.stringValue)!
               
               navigationController?.pushViewController(vc, animated: true)
              
               
           }
           
       }
    
    }
    

}

This is not going to get called when you do this line:
navigationController?.pushViewController(vc, animated: true)

Because the first one is in a closure.

Also this comment, is not true, these are not “global variables” they’re class variables
// Global variables for recieving data from InboxViewController

I’ve actually moved passed that and have done several reiterations and still get that same error. It doesn’t happen when the image is in the assets. It works fine when. It’s in the assets. So when it’s coming from a url, what is the right way to pass the data from one view controller to the next. Mind you this these is a messaging app. So there will be other images in the directory.The network issue doesn’t happen on the first view controller. Only when I select a row does that error occur.

First VC

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

       if indexPath.row >= 0 {
           if let vc = storyboard?.instantiateViewController(identifier: "messageVC") as? MessageViewController {
               let defaultImage = UIImage(named: "arch-delivery-driver")
               vc.imgPosted = UIImage(contentsOfFile: (messenger?.documents[indexPath.row].fields.thumbnail.stringValue)!) ?? defaultImage!
               vc.subjectPosted = (messenger?.documents[indexPath.row].fields.date.stringValue)!
               vc.subjectPosted = (messenger?.documents[indexPath.row].fields.subject.stringValue)!
               vc.bodyPosted = (messenger?.documents[indexPath.row].fields.body.stringValue)!
               
               navigationController?.pushViewController(vc, animated: true)
           }
           
       }
    
    }
    

}

Second VC

type or paste cimport FirebaseAuth
import FirebaseDatabase
import FirebaseFirestore
import FirebaseStorage
import SideMenu
import UIKit


class MessageViewController: UIViewController {
    
    var messenger: Messenger?
    
    //private var inboxViewController = InboxViewController()
    
    @IBOutlet weak var thumbnailMsg: UIImageView!
    @IBOutlet weak var dateMsg: UILabel!
    @IBOutlet weak var subjectMsg: UILabel!
    @IBOutlet weak var bodyMsg: UITextView!
    
    // Variables for recieving data from InboxViewController
    var imgPosted = UIImage()
    var datePosted = ""
    var subjectPosted = ""
    var bodyPosted = ""
    var indexpathForPreviousTableview = IndexPath()
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Recieve data from InboxViewController
    
        thumbnailMsg.image = imgPosted
        dateMsg.text = datePosted
        subjectMsg.text = subjectPosted
        bodyMsg.text = bodyPosted

    }

  
    
}

Watch this so you see what I am trying to do:
https://youtube.com/shorts/IoRB1YNZo2Y?feature=share

What is in messenger.documents?? If it’s nil that means it’s empty for some reason….?

1 Like

messenger.documents is the data model.

Messenger.swift

import Foundation

// MARK: - Messenger
struct Messenger: Decodable {
    let documents: [Document]
}

// MARK: - Document
struct Document: Decodable {
    let name: String
    let fields: Fields
    let createTime, updateTime: String
}

// MARK: - Fields
struct Fields: Decodable {
    let subject, body, thumbnail, date: Body
}

// MARK: - Body
struct Body: Decodable {
    let stringValue: String
}

Is the first code block from this post, how you’re populating the messenger object?