(iOS + Firebase)无法将图像从 UITableViewCell 传递给下一个 ViewController

Posted

技术标签:

【中文标题】(iOS + Firebase)无法将图像从 UITableViewCell 传递给下一个 ViewController【英文标题】:(iOS + Firebase) Unable to pass the Image to the next ViewController from a UITableViewCell 【发布时间】:2018-12-05 08:30:27 【问题描述】:

我有一个UITableView,其中的数据来自 Firebase RealtimeDatabase。一旦用户选择了行,行中的数据,即:标题、描述和图像将被带到下一个 ViewController。

我可以传递标题和描述,但我无法传递图片。

这是我的 UITableView 代码:

import UIKit
import Firebase

class PostTable: UIViewController, UITableViewDelegate, UITableViewDataSource 

    var tableView:UITableView!

    var posts = [Post]()

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView = UITableView(frame: view.bounds, style: .plain)
        view.addSubview(tableView)

        let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
        tableView.register(cellNib, forCellReuseIdentifier: "postCell")
        var layoutGuide:UILayoutGuide!

        layoutGuide = view.safeAreaLayoutGuide

        tableView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true

        tableView.delegate = self
        tableView.dataSource = self
        tableView.tableFooterView = UIView()
        tableView.reloadData()


        observePosts()
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

    func observePosts() 
        let postsRef = Database.database().reference().child("Data")
        print(postsRef)
        postsRef.observe(.value, with:  snapshot in
            var tempPosts = [Post]()

            for child in snapshot.children

                if let childSnapshot = child as? DataSnapshot,
                    let dict = childSnapshot.value as? [String:Any],
                    let title = dict["title"] as? String,
                    let logoImage = dict["image"] as? String,
                    let url = URL(string:logoImage),
                    let description = dict["description"] as? String


                    let userProfile = UserProfile(title: title, photoURL: url)
                    let post = Post(id: childSnapshot.key, title: userProfile, description: description, image: userProfile)
                    print(post)
                    tempPosts.append(post)
                
            

            self.posts = tempPosts
            self.tableView.reloadData()
        )
    

    func getImage(url: String, completion: @escaping (UIImage?) -> ()) 
        URLSession.shared.dataTask(with: URL(string: url)!)  data, response, error in
            if error == nil 
                completion(UIImage(data: data!))
             else 
                completion(nil)
            
            .resume()
    

    func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        print(posts.count)
        return posts.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
        let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
        cell.set(post: posts[indexPath.row])
        return cell
    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        let postsInfo = posts[indexPath.row]
        print(postsInfo)

        let Storyboard = UIStoryboard(name: "Main", bundle: nil)
        let DvC = Storyboard.instantiateViewController(withIdentifier: "PostTableDetailed") as! PostTableDetailed
        DvC.getName = postsInfo.title.title
        DvC.getDesc = postsInfo.description
//        DvC.getImg = postsInfo.title.photoURL
        self.navigationController?.pushViewController(DvC, animated: true)
    

这是第二个 ViewControler,其中包含帖子详细信息:

import UIKit

class PostTableDetailed: UIViewController 

    var getName = String()
    var getDesc = String()

    @IBOutlet weak var Name: UILabel!
    @IBOutlet weak var Description: UILabel!

    override func viewDidLoad() 
        super.viewDidLoad()

        Name.text! = getName
        Description.text! = getDesc     
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    


我还有一些模型(Post、UserProfile)和服务(UserService 和 ImageService),如果需要解决这个问题,请告诉我。

【问题讨论】:

你想要直接传递 UIImage 还是只传递 url?? 我希望UIImage能显示在下一个ViewController中,所以有效率的就行 您可以像在 getName 和 getDesc 中一样在 PostTableDetailed 中简单地传递您的 url,并在 PostTableDetailed 中使用 getImage(url: String..) 方法 或者看我的回答 【参考方案1】:

如果您有 imageUrl,您只需将其从 PostTable 传递到 PostTableDetailed 并下载图像。

   // PostTable
       func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
            let postsInfo = posts[indexPath.row]
            print(postsInfo)

            let Storyboard = UIStoryboard(name: "Main", bundle: nil)
            let DvC = Storyboard.instantiateViewController(withIdentifier: "PostTableDetailed") as! PostTableDetailed
            DvC.getName = postsInfo.title.title
            DvC.getDesc = postsInfo.description
            DvC.getImg = postsInfo.photoURL
            self.navigationController?.pushViewController(DvC, animated: true)
        

// PostTableDetailed
class PostTableDetailed: UIViewController 

    var getName = String()
    var getDesc = String()
    var imageUrl = ""

    @IBOutlet weak var Name: UILabel!
    @IBOutlet weak var Description: UILabel!
    @IBOutlet weak var imageView: UIImageView!


    override func viewDidLoad() 
        super.viewDidLoad()

        Name.text! = getName
        Description.text! = getDesc 
        updayeImage()    
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

 private func updateImage() 
        URLSession.shared.dataTask(with: URL(string: self.imageUrl)!)  data, response, error in
            if error == nil, let data = data 
                imageView.image = UIImage(data: data)
             
            .resume()
    


任务完成时将显示图像。 所以我建议你为 imageView 添加一个微调器。

【讨论】:

尝试在updateImage中绑定图片时出现此错误,Cannot assign value of type 'Data?' to type 'UIImage?' 试试 UIImage(data: data),别忘了解包数据【参考方案2】:

在 PostDetail ViewController 中这样做

import UIKit

class PostTableDetailed: UIViewController 

    var getName = String()
    var getDesc = String()
    var getImg = String()

    @IBOutlet weak var Name: UILabel!
    @IBOutlet weak var Description: UILabel!
    @IBOutlet weak var ImageContainer: UIImageView!

    override func viewDidLoad() 
        super.viewDidLoad()

        Name.text! = getName
        Description.text! = getDesc    
        if let image = getImage(url: getImg)  (image)
            ImageContainer.image = image 
        

    

    override func didReceiveMemoryWarning() 
         super.didReceiveMemoryWarning()
         // Dispose of any resources that can be recreated.
    

    func getImage(url: String, completion: @escaping (UIImage?) -> ()) 
        URLSession.shared.dataTask(with: URL(string: url)!)  data, response, error in
            if error == nil 
                completion(UIImage(data: data!))
             else 
                completion(nil)
            
        .resume()
    


【讨论】:

【参考方案3】:

首先,您可以使用此代码下载图像:

let imageCache = NSCache<AnyObject, AnyObject>()

extension UIImageView 

func downloadImageWithUrlString(urlString: String) -> Void 

    if urlString.count == 0 
        print("Image Url is not found")
        return
    

    self.image = nil
    if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage 
        self.image = cachedImage
        return
    

    let request = URLRequest(url: URL(string: urlString)!)
    let dataTask = URLSession.shared.dataTask(with: request) data, response, error in
        if error != nil  return 
        DispatchQueue.main.async 
            let downloadedImage = UIImage(data: data!)
            if let image = downloadedImage 
                imageCache.setObject(image, forKey: urlString as AnyObject)
                self.image = UIImage(data: data!)
            
        
    
    dataTask.resume()


现在,如果您正在使用包含 Title、Description 和 ImageUrlString 的模型,那么只需将选定的模型对象传递给下一个 viewController。

在下一个 ViewController 中,只需调用相同的方法来下载您在第一个 ViewController 上使用的图像。您不需要将图像从 VC1 传递到 VC2,因为可能图像尚未下载,您选择了一行以移动到下一个 VC。

所以这里简单的事情就是传递模型对象并调用图像下载方法。

【讨论】:

以上是关于(iOS + Firebase)无法将图像从 UITableViewCell 传递给下一个 ViewController的主要内容,如果未能解决你的问题,请参考以下文章

无法从颤振网络将图像上传到 Firebase 存储

无法从 python 服务器将图像上传到 Firebase 存储

如何使用 Firebase Web 将图像从链接保存到 Firebase 存储?

无法将图像从ImageView上传到Android中的FireBase存储

将图像从 firebase 检索到 StaggeredGridLayout Android

将图像从颤振上传到火力基地(没有任何反应)