Getting collection and saving it into array object in firestore swift - ios

I'm trying to save collection into an array of objects called List, and the retrieving is been called in viewdidload by the function loadfirebase. So it actually retrieves the data from firebase and prints it but it doesn't save it in the array. I think it is something that deals with closure but not sure how to fix it.
//
// ContactList.swift
// Socket
//
// Created by dalal aljassem on 12/16/21.
//
import UIKit
import FirebaseFirestore
import FirebaseStorage
class ContactList: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let storage = Storage.storage().reference()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return List.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell" , for:indexPath)
var currentname = List[indexPath.row]
cell.textLabel?.text = currentname.name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
print("some action will happen when i tap here")
}
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadfirebase()
print("**************",List)
}
}
let database = Firestore.firestore()
func loadfirebase()
{
let contactdataRef = database.collection("ContactData")
contactdataRef.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
// var currentDoc = document.data()
print("///////////////")
// print("current doc = " , currentDoc)
print("current name = " , document.get("name")!)
print("current image = " , document.get("image")!)
List.append(Contact(name: document.get("name") as! String, image: document.get("image") as! String, number: ""))
print("\(document.documentID) => \(document.data())")
}
}
}}
}

Your List array is never initialized.
You can achieve this with the following code:
var List: [Contact] = []
and I would put this before the declaration of tableView function.

Related

Displaying images fetched from firebase in tableview

I am trying to retrieve data from firebase and display them in a tableview but my code for some reason is not working. I am getting the images and appending them into a list but that list is not having any data outside the else block.
With my implementation, I am getting a blank tableview. Could someone help with me this please?
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
let db = Firestore.firestore()
var usersReference = Firestore.firestore().collection("users")
var storageReference = Storage.storage().reference()
var imagesList = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
usersReference.addSnapshotListener { [self] (querySnapshot, error) in
querySnapshot?.documents.forEach() {
(document) in
let uid = document.data()["uid"] as! String
let imagePath = "profilePictures/\(uid).jpg"
let imgRef = storageReference.child(imagePath)
imgRef.getData(maxSize: 1 * 2048 * 2048) { data, error in
if let error = error {
print(String(describing: error))
}
else {
DispatchQueue.main.async {
let image = UIImage(data: data!)
imagesList.append(image!)
print("inside viewDidLoad: ", imagesList.count)
}
}
}
}
}
print(imagesList.count)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return imagesList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath)
print("cellForRowAt: ",imagesList.count)
cell.textLabel?.text = "\(indexPath.row)"
cell.imageView?.image = imagesList[indexPath.row]
return cell
}
This is how my simulator looks like when I run the code: compiled code .

How to get Firestore documents and display them on a UITableView

Screenshot of Firestore Project
I want to display the "first_name" field for each document in the collection (In the UITableView. The UITableView just shows up blank every time I run the app.
CODE:
import UIKit
import Firebase
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var filterButton: UIButton!
#IBOutlet weak var userTableView: UITableView!
var usersArray = [String]()
var db: Firestore!
override func viewDidLoad() {
super.viewDidLoad()
userTableView.delegate = self
userTableView.dataSource = self
// Do any additional setup after loading the view.
db = Firestore.firestore()
loadData()
}
func loadData() {
db.collection("users").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
self.usersArray.append(document.documentID)
}
}
print(self.usersArray)
self.userTableView.reloadData()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Tableview setup \(usersArray.count)")
return usersArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = userTableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! UserCell
let user = usersArray[indexPath.row]
cell.fullNameLabel.text = user
print("Array is populated \(usersArray)")
return cell
}
}
Doesn't look like you registered the cell to the tableView. Try using: tableview.register(UserCell,forCellReuseIdentifier:"Your reuseIdentifier string"). Try inserting this in viewDidLoad.

How to get the name list on Realm database and display on my stimulator?

Here I have a Realm Database which is have some data in it and I want to display it on my Stimulator but it turn out display some other thing. What's wrong in my code?
This is the data of my Realm Database and I also marked the data which I want to display it.
The stimulator which display something like this.
And here is my ViewController.swift code's.
import UIKit
import RealmSwift
class ViewController: UIViewController,UITableViewDataSource { //UITableViewDataSource
#IBOutlet weak var mytableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let realm = try! Realm()
let theItem = realm.objects(Item.self).filter("itemid >= 1")
return theItem.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let realm = try! Realm()
let theItem = realm.objects(Item.self).filter("itemid >= 1")
print(theItem)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1")
//I suspect the problem is at here...
cell?.textLabel?.text = "\(theItem)"
return cell!
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
class Category: Object {
#objc dynamic var name: String?
#objc dynamic var caid: Int = 0
}
class Item: Object {
#objc dynamic var name: String?
#objc dynamic var itemid: Int = 0
#objc dynamic var cateid: Int = 0
}
Your problem is that you need to get the string from the Item object. try something like
"\(theItem.name)".
func getNames() -> [String]{
let items = realm.objects(Item.self).filter("itemid >= 1").toArray(ofType: Item.self ) as [Item]
return items.map { $0.name }
}
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
var array = [T]()
for i in 0 ..< count {
if let result = self[i] as? T {
array.append(result)
}
}
return array
}
}
I found a way to display the data already. I just need to add indexPath.row in my code and it can handle the data already.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let realm = try! Realm()
let theItem = realm.objects(Item.self).filter("itemid >= 1")
//I only add below this indexpath
let cellData = theItem[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1")
//and change this part and it's done.
cell?.textLabel?.text = cellData.name
print(theItem)
return cell!
}

Downloading file names from firebase storage

As i read in the documentation i can access single url in firebase storage like this:
`// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors }
else {
// Get the download URL for 'images/stars.jpg'
} }`
However, i have many files there, so how can i skip giving direct path and instead iterate through all files in the given directory?
Thanks for tips.
DownloadURL takes single string at a time. In case you want to show all the files inside a folder to a tableview like me, here is the
full code:
import UIKit import Firebase
My very First View Controller-
class FolderList: UIViewController {
var folderList: [StorageReference]?
lazy var storage = Storage.storage()
#IBOutlet weak var tableView : UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.storage.reference().child("TestFolder").listAll(completion: {
(result,error) in
print("result is \(result)")
self.folderList = result.items
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
} }
extension FolderList : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return folderList?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "FolderListCell", for:
indexPath) as? FolderListCell else {return UITableViewCell()}
cell.itemName.text = folderList?[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 64.0
} }
extension FolderList : UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
guard let downloadVC = storyBoard.instantiateViewController(withIdentifier:
"DownloadedItemView") as? DownloadedItemView else {
return
}
downloadVC.storageRef = folderList?[indexPath.row]
self.navigationController?.pushViewController(downloadVC, animated: true)
}
}
You each cell:
class FolderListCell: UITableViewCell {
#IBOutlet weak var itemName : UILabel!
}

tableView Cell not displaying data, What's the issue? (Swift 3)

So I have a view controller that is parsing some bitcoin price data. The function successfully responds and parses the data, but I cannot seem to get it to display in tableView.
I have already tested the outlets and identities via a test cell, which does work.
What am I doing wrong?
Code: `
import UIKit
import Alamofire
import AlamofireObjectMapper
import ObjectMapper
class Response: Mappable{
var data: [Amount]?
required init?(map: Map){
}
func mapping(map: Map) {
data <- map["data"]
}
}
class Amount: Mappable {
var data : String?
required init?(map: Map){
}
func mapping(map: Map) {
data <- map["data.amount"]
}
}
class ViewController: UIViewController, UITableViewDelegate,
UITableViewDataSource {
var mount = [String]()
var am = [String]()
#IBOutlet var tableView: UITableView!
func Call_bitcoin() {
let url = "https://api.coinbase.com/v2/prices/BTC-USD/buy"
Alamofire.request(url).responseObject{ (response: DataResponse<Amount>) in
let mount = response.result.value
let am = mount?.data
self.tableView.reloadData()
return
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
Call_bitcoin()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return am.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
print(am)
cell.textLabel?.text = am[indexPath.row]
return cell
}
}
`
You want to add elements in your Call_bitcoin() function but you are doing it wrong. You have already created var am = [String](). So you don't need to use let am = mount?.data. You could add your data in your am variable which is already created. You need to change some of your code lines in Call_bitcoin() function:
From:
let mount = response.result.value
let am = mount?.data
To:
let mount = response.result.value
am.append(mount?.data) // This part should be set by your 'mount?.data' value type
Your JSON not returning array, it's having dictionary.that why you get
am.count = 0
Solve first your data and put data into the array.
{"data":{"amount":"2414.88","currency":"USD"},"warnings":[{"id":"missing_version","message":"Please supply API version (YYYY-MM-DD) as CB-VERSION header","url":"https://developers.coinbase.com/api#versioning"}]}

Resources