【问题标题】:Why does my TableView only show the last image loaded in every cell? (swift)为什么我的 TableView 只显示每个单元格中加载的最后一张图片? (迅速)
【发布时间】:2019-11-22 20:46:29
【问题描述】:

我目前遇到的问题是在 tableView 单元格中正确显示图像。我的图像已保存到 Firebase,我可以轻松检索这两个图像。

当我尝试在其自己的表格视图单元格中显示每个图像时,它们会快速加载两个图像,最终结果是最后一个图像显示在两个单元格中,而不是两个不同的图像。

我认为问题在于我的 cellForRowAt IndexPath 或我如何从 Firebase 调用数据。

这是我的主 TableView 视图控制器

import UIKit
import Firebase
import FirebaseStorage
import FirebaseDatabase

class CardDesignViewController: UIViewController {

@IBOutlet weak var tableView: UITableView!
//passing a value to another page with thie var
var IdvalueTitle = ""
var db:Firestore!
//PropertiesCell2 is pointing to a swift file containing my dictionary for the outlets
var propertiesArray3 = [PropertiesCell2]()

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self


extension CardDesignViewController: UITableViewDataSource, UITableViewDelegate {


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return propertiesArray3.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let spot = propertiesArray3[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableView2") as! TableView2


    cell.app? = "\(spot.templateOption)"

    cell.IDvalueHidden?.text = "\(spot.IDvalueHidden)"
    cell.templateOption.layer.cornerRadius = 12
    cell.templateOption.layer.masksToBounds = true

    return cell

}

我已将单元格的出口放入一个名为“TableView2”的文件中。这是我在名为 getTemplates() 的函数中调用来自 Firebase 的图像数据的地方,并在“var app: String!”中使用它

import Foundation
import UIKit
import Firebase
import FirebaseDatabase
import FirebaseStorage

class TableView2: UITableViewCell {

@IBOutlet weak var templateOption: UIImageView!
@IBOutlet weak var IDvalueHidden: UILabel!

func  styleTheCells2(cells: Cell2) {

    templateOption.image = cells.templateOption
    IDvalueHidden.text = cells.IDvalueHidden
}
var app: String! {
    didSet {
        self.getTemplates()
    }
}
func getTemplates() {

    let db = Firestore.firestore()

    db.collection("Card Templates").getDocuments { (snapshot, err) in
        if err != nil {
            return
        } else {
            for document in (snapshot?.documents)! {
                if let picURL = document.data()["Template"] as? String {
                    let url = URL(string: picURL)
                    print(picURL)
                    DispatchQueue.global().async {
                        do{
                            let data = try Data(contentsOf: url!)
                            DispatchQueue.main.async {
                                self.templateOption.image = UIImage(data: data)
                            }
                        } catch {
                        }
                    }
                }
            }
        }
    }
}

当我运行此代码时,我还附上了一张最终结果的图片。但是,我在两个单元格中都得到了相同的图像,当我查看调试区域时,我可以看到两个图像都被访问了两次。

这是我运行此代码时的模拟器。我希望在单元格中有两个不同的图像,而不是两个图像:

我的调试器显示两个图像 url 被连续拉出两次,最后一个被拉出的图像(绿色图像)显示在两个单元格中:

【问题讨论】:

  • 设置断点后,我可以看到 call.app 不为零。我在 app:String 的“didSet”下有 getTemplates() 函数。你是在建议我在那里改变一些东西,如果是这样怎么办?谢谢!
  • 在您的 tableView func tableView(_ tableView: UITableView 中,您正在创建一个 TableView2 类型的单元格(顺便说一句,这是一个奇怪的单元格名称)但随后该函数返回一个UITableViewCellindexPath: IndexPath) -> UITableViewCell。这是故意的吗?
  • 你是对的,即使我使用 cell.app,它也会拉出相同的绿色图像? =“另一个图像”。如果这有意义
  • Jay,老实说,我是 swift 新手,我相信 UITableViewCell 是我需要使用的,但我愿意尝试其他方法。
  • Sammy,这会返回错误,因为 app 不是我的 Firebase 中的定义术语。 Ashmit Bhui 在下面回答说,当我调用我的数据时,我陷入了 for 循环,这就是它循环遍历数据并落在最后一张图像上的原因。

标签: ios swift xcode firebase uitableview


【解决方案1】:

每次通过 getTemplates() 函数呈现 UITableViewCell 时,您都会从 Firebase 存储中获取图像

由于您在 Firebase 中有 2 个图像,我假设“propertiesArray3”中有 2 个元素。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return propertiesArray3.count
}

每次它通过 Firebase 并打印出数据库中的所有 URL。由于 numberOfRowsInSection 为 2,图像 URL 被打印两次。

for循环每次都在最后一个元素结束,并将最后一个URL设置为图片。

func getTemplates() {

let db = Firestore.firestore()

db.collection("Card Templates").getDocuments { (snapshot, err) in
    if err != nil {
        return
    } else {
        for document in (snapshot?.documents)! {
            if let picURL = document.data()["Template"] as? String {
                let url = URL(string: picURL)
                print(picURL)
                DispatchQueue.global().async {
                    do{
                        let data = try Data(contentsOf: url!)
                        DispatchQueue.main.async {
                            self.templateOption.image = UIImage(data: data)
                        }
                    } catch {
                    }
                }
            }
        }
    }
}

希望对你有帮助

对于开始的基本方法,您可以尝试这样的方法 - 声明一个数组来存储 URL

var urlArray: [URL] = []

在 viewDidLoad() 中获取 URL

let db = Firestore.firestore()
db.collection("Card Templates").getDocuments { (snapshot, err) in
    if err != nil {
        return
    } else {
        for document in (snapshot?.documents)! {

            if let picURL = document.data()["Template"] as? String {
                let url = URL(string: picURL)
                // ADD ALL THE URLs TO THE NEW ARRAY
                urlArray.append(url)                    
            }
        }
        tableView.reloadData()
    }
}

从 UITableViewCell 中移除 getTemplates()

编辑 tableView 委托

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return urlArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let spot = propertiesArray3[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableView2") as! TableView2

    let url = urlArray[indexPath.row]
    do{
        let data = try Data(contentsOf: url!)
        DispatchQueue.main.async {
            cell.templateOption.image = UIImage(data: data)
        }
      } catch {
      }


    cell.app? = "\(spot.templateOption)"

    cell.IDvalueHidden?.text = "\(spot.IDvalueHidden)"
    cell.templateOption.layer.cornerRadius = 12
    cell.templateOption.layer.masksToBounds = true

    return cell

} 

【讨论】:

  • 这解释了我的两个问题都存在的问题!我是新手太快了,显然还没有掌握 for 循环。您如何建议在那里修改代码?非常感谢!
【解决方案2】:

prepareForReuse 函数中最清晰的基于内容的单元格视图

override func prepareForReuse() {
        super.prepareForReuse()

        // remove image from imageView
        templateOption.image = nil
    } 

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 2019-01-13
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-21
    相关资源
    最近更新 更多