(iOS+;Firebase)无法将图像从UITableViewCell传递到下一个ViewController
我有一个(iOS+;Firebase)无法将图像从UITableViewCell传递到下一个ViewController,ios,swift,firebase,uitableview,Ios,Swift,Firebase,Uitableview,我有一个UITableView,其中数据来自Firebase实时数据库。一旦用户选择该行,该行中的数据(即:标题、说明和图像)将被传送到下一个ViewController 我可以传递标题和描述,但无法传递图像 以下是我的UITableView代码: import UIKit import Firebase class PostTable: UIViewController, UITableViewDelegate, UITableViewDataSource { var tableV
UITableView
,其中数据来自Firebase实时数据库。一旦用户选择该行,该行中的数据(即:标题、说明和图像)将被传送到下一个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,其中包含post详细信息:
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),请告诉我这是否是解决此问题所必需的。如果您有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中添加一个微调器。如果您有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添加微调器。在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()
}
}
在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()
}
}
首先,您可以使用以下代码下载图像:
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()
}
}
让imageCache=NSCache()
扩展UIImageView{
func下载ImageWithUrlString(urlString:String)->Void{
如果urlString.count==0{
打印(“未找到图像Url”)
返回
}
self.image=nil
如果让cachedImage=imageCache.object(forKey:urlString作为AnyObject)作为?UIImage{
self.image=cachedImage
返回
}
let request=URLRequest(url:url(string:urlString)!)
让dataTask=URLSession.shared.dataTask(with:request){data,response,中的错误
如果错误!=nil{return}
DispatchQueue.main.async{
让我们下载eImage=UIImage(数据:数据!)
如果let image=downloadeImage{
setObject(image,forKey:urlString作为AnyObject)
self.image=UIImage(数据:data!)
}
}
}
dataTask.resume()
}
}
现在,如果您使用的模型包含标题、描述和ImageUrlString,那么只需将所选模型对象传递给下一个viewController即可
在下一个ViewController中,只需调用相同的方法下载您在第一个ViewController上使用的图像。您不需要将映像从VC1传递到VC2,因为可能映像尚未下载,您可以选择一行在下一个VC上移动
这里是传递模型对象并调用图像下载方法的简单方法 首先,您可以使用以下代码下载图像:
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()
}
}
让imageCache=NSCache()
扩展UIImageView{
func下载ImageWithUrlString(urlString:String)->Void{
如果urlString.count==0{
打印(“未找到图像Url”)
返回
}
self.image=nil
如果让cachedImage=imageCache.object(forKey:urlString作为AnyObject)作为?UIImage{
self.image=cachedImage
返回
}
let request=URLRequest(url:url(string:urlString)!)
让dataTask=URLSession.shared.dataTask(with:request){data,response,中的错误
如果错误!=nil{return}
DispatchQueue.main.async{
让我们下载eImage=UIImage(数据:数据!)
如果let image=downloadeImage{
setObject(image,forKey:urlString作为AnyObject)
self.image=UIImage(数据:data!)
}
}
}
dataTask.resume()
}
}
现在,如果您使用的模型包含标题、描述和ImageUrlString,那么只需将所选模型对象传递给下一个viewController即可
在下一个ViewController中,只需调用相同的方法下载您在第一个ViewController上使用的图像。您不需要将映像从VC1传递到VC2,因为可能映像尚未下载,您可以选择一行在下一个VC上移动
这里是传递模型对象并调用图像下载方法的简单方法 您希望直接传递UIImage还是仅传递url?我希望UIImage显示在下一个ViewController中,因此无论效率如何,您都可以像传递getName和getDesc一样,在PostTableDetailed中传递url,并使用方法getImage(url:String..)在PostTableDetailed中或查看我的回答您希望直接传递UIImage还是仅传递url?我希望UIImage显示在下一个ViewController中,因此,无论效率如何,您都可以简单地在PostTableDetailed中传递url,就像在getName和getDesc中传递url一样,并使用方法getImage(url:String..)在PostTableDetailed或watch my answer中,当它尝试在updateImage中绑定图像时会出现此错误,
无法将类型“Data?”的值分配给类型“UIImage”
尝试UIImage(数据:Data),别忘了打开数据当它尝试在updateImage中绑定图像时会出现此错误,无法将“数据”类型的值指定给“UIImage”类型。
请尝试UIImage(数据:数据),不要忘记展开数据