(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的主要内容,如果未能解决你的问题,请参考以下文章
无法从 python 服务器将图像上传到 Firebase 存储
如何使用 Firebase Web 将图像从链接保存到 Firebase 存储?
无法将图像从ImageView上传到Android中的FireBase存储