Reputation: 11
The problem I have have at the moment is properly displaying images in a tableView cell. My images are saved to Firebase, and I can easily retrieve both images.
When I try to display each image in its own table view cell they quickly load both images and the end result is the last image displaying in both cells instead of two different images.
I believe the issue is either with my cellForRowAt IndexPath or how I am calling the data from Firebase.
This is my Main TableView View Controller
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
}
I have put my outlets for the cells into a file called "TableView2". This is where I call the data for the images from Firebase in a func called getTemplates() and use that within "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 {
}
}
}
}
}
}
}
I've attached a picture as well of the end result when I run this code. I get the same image in both cells however, when I look at the debug area I can see that both images were accessed twice.
This is my simulator when I run this code. Im looking to have two different images in the cells rather than the one picture in both:
My debugger shows both image urls being pulled twice consecutively and the last image pulled (the green image) shows in both cells:
Upvotes: 1
Views: 645
Reputation: 36
You are fetching the images from Firebase Storage each time UITableViewCell is being presented via getTemplates() function
Since you have 2 images in Firebase, I am assuming 'propertiesArray3' has 2 elements in it.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return propertiesArray3.count
}
Each time it goes through the Firebase and prints out all the URLs in the db. As the numberOfRowsInSection is 2, the Image URL are being printed twice.
The for loop ends at the last element each time and sets the last URL as the image.
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 {
}
}
}
}
}
}
Hope it helps
For a basic approach to start with, you can try something like this - Declare an array to store the URL
var urlArray: [URL] = []
Fetch the URLs in viewDidLoad()
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()
}
}
Remove getTemplates() from UITableViewCell
Edit the tableView Delegate
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
}
Upvotes: 1
Reputation: 44
You most clear content based Views of cell in prepareForReuse function
override func prepareForReuse() {
super.prepareForReuse()
// remove image from imageView
templateOption.image = nil
}
Upvotes: 0