简体   繁体   中英

pass an image from one view controller to another (swift) with Firebase

i am trying to pass an image from one view controller to another but i am getting an error in prepare for segue function

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {


        let post = posts[indexPath.row]

        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)as? collectionViewCellBooks {

            if let img = booksVC.imageCache.object(forKey: post.imageUrl as NSString) {
                cell.configureCell(post: post, img: img)
                return cell

        }else {

                cell.configureCell(post: post)
                return cell
            }
        }
            else {
                return collectionViewCellBooks()
            }

    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.performSegue(withIdentifier: "showImage", sender: self)
    }



    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {

         if segue.identifier == "showImage"
         {

         let indexPaths = self.collectionView!.indexPathsForSelectedItems!
         let indexPath = indexPaths[0] as IndexPath
         let vc = segue.destination as! newViewController
        // vc.image = self.posts[(indexPath as NSIndexPath).row]
            vc.image = self.posts[indexPath.row]
         }





class newViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    var image = UIImage()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.imageView.image = self.image
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

this is my Post class

class Post {

private var _caption: String!
private var _imageUrl: String!
private var _postKey: String!



var caption: String {
    return _caption
}

var imageUrl: String {
    return _imageUrl
}

var postKey: String {
    return _postKey
}


init(caption: String, imageUrl: String) {

    self._caption = caption
    self._imageUrl = imageUrl
}

init(postKey: String, postData: Dictionary<String, AnyObject>) {

    self._postKey = postKey

    if let caption = postData["title"] as? String {
        self._caption = caption
    }
    if let imagesUrl = postData["imageURL"] as? String {
        self._imageUrl = imagesUrl
    }

}

}

title and imageURL are saved on firebase database

You are getting the error because you are not sending an image to the new viewController but an instance of your Post class, which by the way doesn't even contain an image (only an imageURL). You have to extract the image from the server first before you can parse it anywhere.

You should parse the whole post as you are doing it right now and download the image via the postID directly in the new ViewController. (in case you saved the image in Firebase storage) I always end up parseing the whole object because later in the development you maybe decide to show more properties in the newViewController. If you parsed the whole object you don't have to change your code structure anymore.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "your Identifier" {
            if let vc = segue.destination as?  NewViewController {
                if let post = sender as? Post {
                    vc.post = post
                }
            }
        }
    }

in your didSelectIdemAt function you need to change the sender of the performSegue function:

 performSegue(withIdentifier: "your Identifier", sender: post)

now your newViewController has a little bit more code but that is how i do it and it works stable.

let reference = FIRDatabase.database().reference()
reference.child("posts").child("<postID>").observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
print(snapshot.value)

if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
    for snap in snapshots {

        if let postsDict = snap.value as? Dictionary<String, AnyObject> {

            if let imageURL = postsDict["imageURL"] as? String {
                let httpsReference = FIRStorage.storage().reference(forURL: imageURL)
                httpsReference.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
                if error != nil {
                    print("error... couldn't get picture from Server \(error.localizedDescription)")
                    } else {
                        let image = UIImage(data: data!)
                        self.img = image! // you need to create this variable somewhere in your viewController Class before this code
                        //"your UIImageVIew.image" = img AND THAT IS IT
                    }
                }
            }
        }
    }
}

Can you try with following change in preparefor segue method.. let me know

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    {

         if segue.identifier == "showImage"
         {

         let indexPaths = self.collectionView!.indexPathsForSelectedItems!
         let indexPath = indexPaths[0] as IndexPath
         let vc = segue.destinationViewController as! newViewController

         let post = posts[indexPath.row]
         if let img = booksVC.imageCache.object(forKey: post.imageUrl as NSString) {
                vc.image = img
         }
       }
    }


class newViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    var image = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        if self.image {
         self.imageView.image = self.image
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM