I'm working on a car rental app, which accepts user's input and putting it in my SQLite Database.
Inside my tableview viewcontroller, it is displaying the informations fine.
Example:
Cell 1: Toyota, Philippines, 5000
Cell 2: Nissan, America, 1000
Cell 3: Mitsubishi, England, 2000
The problem is, whenever I search, for example I searched the "england", the only right data it is displaying is only the location. So it will display like this:
Cell 1: Toyota, England, 5000
which is Toyota and 5000 is coming from the index 0. and the only right data is England.
My desired result whenever I search "england":
Cell 1: Mitsubishi, England, 2000
Please help me fixing the car type and rate to display it also.
This is my code inside my table view controller:
import UIKit
import SQLite
class CarList: UIViewController, UITableViewDataSource, UITableViewDelegate,
UISearchBarDelegate {
#IBOutlet var tableView: UITableView!
#IBOutlet var searchBar: UISearchBar!
//variables I used to append my database
var carType = [String]()
var rate = [String]()
var location = [String]()
//variables I used to append my filtered data for searchbar
var filteredLocation: [String]!
var filteredCar: [String]!
var filteredRate: [String]!
var img = [UIImage(named: "Toyota"), UIImage(named: "Nissan")]
override func viewDidLoad() {
super.viewDidLoad()
searchBar.placeholder = "Search Location"
do{
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory.appendingPathComponent("users").appendingPathExtension("sqlite3")
let database = try Connection(fileUrl.path)
Variables.database = database
}catch {
print(error)
}
//appending my database to my array
do{
let users = try Variables.database.prepare(Variables.rTable)
for user in users {
carType.append(user[Variables.rCar])
rate.append(user[Variables.rRate])
location.append(user[Variables.rLocation])
}
}catch{
print(error)
}
searchBar.delegate = self
//assigning the array to filtered data
filteredLocation = location
filteredCar = carType
filteredRate = rate
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredLocation.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CarListCell
cell.carType.text = "Car Type: " + filteredCar[indexPath.row]
cell.rate.text = "Location: " + filteredLocation[indexPath.row]
cell.carImage.image = UIImage(named: filteredCar[indexPath.row]+".jpg")
return (cell)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredLocation = searchText.isEmpty ? location : location.filter({(dataString: String) -> Bool in
return dataString.range(of: searchText, options: .caseInsensitive) != nil
})
tableView.reloadData()
}
//below is the code when I clicked on the table view cell, it will pass the data.
//but the filtered location is the only one working.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "info" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let controller = segue.destination as! CarInfo
controller.getCar = filteredCar[indexPath.row]
controller.getRate = filteredRate[indexPath.row]
controller.getLocation = filteredLocation[indexPath.row]
}
}
}
} // End Class
And this is my database table in case you need it, I separated it using Variables.swift.
import Foundation
import UIKit
import SQLite
class Variables: UIViewController{
var database: Connection!
let rTable = Table("rTable")
let rId = Expression<Int>("rId")
let rCar= Expression<String>("rCar")
let rLocation = Expression<String>("rLocation")
let rRate = Expression<String>("rRate")
}
Rather than make 3 arrays for your data, you can make object for them
class Car{
var carType:String?
var location:String?
var rate:String?
}
Then rather
var filteredLocation: [String]!
var filteredCar: [String]!
var filteredRate: [String]!
make this
var cars = [Car]()
and rather than
for user in users {
carType.append(user[Variables.rCar])
rate.append(user[Variables.rRate])
location.append(user[Variables.rLocation])
}
make this
for user in users {
let car = Car()
car.carType = user[Variables.rCar]
car.location = user[Variables.rLocation]
car.rate = user[Variables.rRate]
cars.append(car)
}
and cellForRow change it to
cell.carType.text = "Car Type: " + cars[indexPath.row].carType
cell.rate.text = "Location: " + cars[indexPath.row].rate
cell.carImage.image = UIImage(named: cars[indexPath.row].carType+".jpg")
and the important thing is that
filteredCars = cars.filter{
$0.carType.lowercased == searchText.lowercased}
}
where filteredCars is array of car object . Hope this help you .
Related
I am making a simple messaging app in xcode. The table view is populated with custom cells that contain a right and left view. When the user receives a message the left view is populated and when the user sends a message the right view is populated.
The PROBLEM is after reloading the tableView sometimes I will see cells filled with scrambled data from the array containing the messages. I'm not sure what is happening.
Things I've tried:
I've checked the message files that are stored on my backend in Back4App and they all contain the corrent csv data
I looked at my cell count which is always accurate
I've printed the array and cell data before the table reloads and after it reloads and the data in the array's is all correct.
If I leave the message VC and return to it all the messages are displayed correctly but when I stay in the VC and use the send button to send messages the data gets scrambled a little and prints weird combinations of my tableView
You can see the bottom line is not displayed correctly:
Image showing the error
Here is my chat VC:
//
// ChatViewController.swift
// Glam
//
// Created by Student on 11/14/20.
// Copyright © 2020 Tucker Weibell. All rights reserved.
//
import UIKit
import Parse
class ChatViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var navTitle: UINavigationItem!
var senders = [String]()
var message = [String]()
var state = [String]()
#IBOutlet weak var textView: UITextView!
#IBOutlet weak var myView: UIView!
#IBOutlet weak var bottomConstraint: NSLayoutConstraint!
var dataStringSender = ""
var dataStringReciever = ""
var senderName = ""
override func viewDidLoad() {
super.viewDidLoad()
getData()
navTitle.title = MessageCustomerViewController.GlobalVars.selectedItem
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
self.view.addGestureRecognizer(tap)
}
func getData() {
let user = PFUser.current()
let username = user?.username
senderName = username!
let query = PFUser.query()
query?.whereKey("username", equalTo: username!)
do {
let result = try query?.findObjects()
let file = result![0]["Messages"] as! PFFileObject
do {
let data = try file.getData()
let string = String(decoding: data, as: UTF8.self)
dataStringSender = string
let cvsRows = string.components(separatedBy: "\n")
for row in cvsRows {
var itemsRow = row.components(separatedBy: ",")
print(itemsRow)
itemsRow[2] = itemsRow[2].replacingOccurrences(of: "\r", with: "")
print(itemsRow)
if itemsRow[0] == MessageCustomerViewController.GlobalVars.selectedItem {
senders.append(itemsRow[0])
message.append(itemsRow[1])
state.append(itemsRow[2])
}
}
}
catch {
print(error.localizedDescription)
}
}
catch {
print(error.localizedDescription)
}
loadData()
}
#IBAction func sendMessage(_ sender: Any) {
let query = PFUser.query()
query?.whereKey("username", equalTo: MessageCustomerViewController.GlobalVars.selectedItem)
do {
let result = try query?.findObjects()
if result?[0]["Messages"] != nil {
let file = result![0]["Messages"] as! PFFileObject
do {
let data = try file.getData()
let string = String(decoding: data, as: UTF8.self)
dataStringReciever = string
}
catch {
print(error)
}
}
}
catch {
print(error)
}
dataStringSender = dataStringSender + "\n" + MessageCustomerViewController.GlobalVars.selectedItem + "," + textView.text + "," + "Sent"
dataStringReciever = dataStringReciever + "\n" + senderName + "," + textView.text + "," + "Recieved"
let dataSent = Data(dataStringSender.utf8)
let dataRecieved = Data(dataStringReciever.utf8)
//let fileSent: PFFileObject = PFFileObject(data: dataSent)!
//let fileRecieved: PFFileObject = PFFileObject(data: dataRecieved)!
let fileSent = PFFileObject(name: "message.csv", data: dataSent)
let fileRecieved = PFFileObject(name: "message.csv", data: dataRecieved)
let user = PFUser.current()
user!["Messages"] = fileSent
user?.saveInBackground()
let newQuery = PFUser.query()
newQuery?.whereKey("username", equalTo: MessageCustomerViewController.GlobalVars.selectedItem)
do {
let newResults = try newQuery?.findObjects()
newResults![0]["Messages"] = fileRecieved
newResults![0].saveInBackground()
}
catch {
print(error)
}
clearData()
getData()
print("\n")
print("\n")
print(message)
print("\n")
print("\n")
print(state)
loadData()
}
func loadData() {
self.tableView.reloadData()
}
func clearData() {
message.removeAll()
state.removeAll()
senders.removeAll()
}
#objc func handleKeyboardNotification(notification: NSNotification) {
if let keyboardFrame: NSValue = notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
var height = keyboardRectangle.height
height = height * -1
bottomConstraint.constant = height + 85
}
}
#objc func dismissKeyboard(sender: UITapGestureRecognizer) {
bottomConstraint.constant = 0
textView.resignFirstResponder()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return message.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print([message[indexPath.row]])
let cell = tableView.dequeueReusableCell(withIdentifier: "messagescell") as! MessagesCell
if state[indexPath.row] == "Sent" {
cell.sentText.text = message[indexPath.row]
cell.sentView.backgroundColor = .clear
}
else {
cell.recievedText.text = message[indexPath.row]
cell.recievedView.backgroundColor = .clear
}
return cell
}
}
That sounds a lot like an reusable cell issue.
Since you are reusing your cells here let cell = tableView.dequeueReusableCell(withIdentifier: "messagescell") as! MessagesCell the properties of those cells happen to have old states from time to time if you not explicitly set new values to all of them.
You should override prepareForReuse() in your custom cell implementation and reset your cell to default values.
I just began to learn Firebase a week ago, but right now I am facing a problem of not able to load image from Firebase to my TableViewCell. I can retrieve data such as text information and the URL of the image from Firebase Realtime Database but not able to make use of those URL in order to fire up image on the TableViewCell. May you all help me identify the problems? I can retrieve everything such as text information as well as the image URL but how can I make the image pop up on the cell? All your help would be highly appreciate!
This is the ViewController that responsible to display the TableViewCell
import UIKit
import Firebase
import FirebaseStorage
class NewsFeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var rubthort:String = ""
var linkRub:String?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrItem.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! NewsFeed
// textlabel
// detailtextlabel
cell.textLabel?.text = arrItem[indexPath.row].name
cell.detailTextLabel?.text = arrItem[indexPath.row].price
//cell.imageView?.image = UIImage(named: "flower")
// Get image
let id = RetrieveData()
if let imageLink = self.linkRub {
let url = URL(string: imageLink)
//let data = NSData(contentsOf: url!)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// download hit an error so return out
if error != nil {
print(error)
return
}
DispatchQueue.main.async {
cell.imageView?.image = UIImage(data: data!)
}
}.resume()
}
return cell
}
let ref = Database.database().reference()
// Array of PlasticItem
var arrItem = [RetrieveData]()
#IBOutlet weak var tblView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
retrieveData()
} // Ends of viewDidLoad
func retrieveData() {
// Getting a node from database
let retRef = ref.child("item/electronic")
// Observing data changes
retRef.observe(DataEventType.value) { (dataSnapshot) in
// Remove array item everytime there is a new reference to the data in Firebase
self.arrItem.removeAll()
// Check if there are any children or second object inside the parent object
if dataSnapshot.childrenCount > 0 {
// Loop over all children's object
for post in dataSnapshot.children.allObjects as! [DataSnapshot] {
let object = post.value as! [String: Any]
let getName = object["name"] as! String
let getPrice = object["price"] as! String
let getImage = object["itemURL"] as! String
print(getName)
print(getPrice)
print(getImage)
self.linkRub = getImage
self.arrItem.append(RetrieveData(cat: "", name: getName, price: getPrice, rub: getImage))
}
self.tblView.reloadData()
}// Ends of if statement
else if dataSnapshot.childrenCount == 0{
print("No Data Found")
}
} // Ends of retRef.observe
} // Ends of retrieveData()
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
This is the model struct
import Foundation
import UIKit
struct RetrieveData{
var cat: String
var name: String
var price: String
var rub: String?
init(){
self.cat = ""
self.name = ""
self.price = ""
self.rub = ""
}
init(cat:String, name:String, price:String, rub: String){
self.cat = cat
self.name = name
self.price = price
self.rub = rub
}
}
What I got so far is a tableView and custom Cells about hookah tobacco. Those include an image, name, brand and ID. Now what I try to reach is basically a tableview that contains only the cells with attributes based on a "filter". For example the tableView that appears at the beginning has only the following two settings to make it simple: PriceRange and BrandName. At the first time loading the tableView those are PriceRange: 0 - 100 and Brands: all brands. Then imagine a user restricting those like 0 - 15 Euros and only brand called "7 Days". How exactly would I do that with reloading the tableView?
import UIKit
import Firebase
class ShopViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var button_filter: UIBarButtonItem!
#IBOutlet weak var searchBar_shop: UISearchBar!
#IBOutlet weak var view_navigator: UIView!
#IBOutlet weak var tableView_shop: UITableView!
var ShopCells: [ShopCell] = []
var databaseRef: DatabaseReference!
var storageRef: StorageReference!
override func viewDidLoad() {
super.viewDidLoad()
self.databaseRef = Database.database().reference()
self.storageRef = Storage.storage().reference()
createArray() { shopCells in
for item in shopCells {
self.ShopCells.append(item)
}
DispatchQueue.main.async {
self.tableView_shop.reloadData()
}
}
self.navigationItem.title = "Shop"
self.tableView_shop.delegate = self
self.tableView_shop.dataSource = self
self.searchBar_shop.delegate = self
self.searchBar_shop.barTintColor = UIColor(hexString: "#1ABC9C")
self.view_navigator.backgroundColor = UIColor(hexString: "#1ABC9C")
self.tableView_shop.separatorColor = UIColor.clear
self.searchBar_shop.isTranslucent = false
self.searchBar_shop.backgroundImage = UIImage()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ShopViewController.viewTapped(gestureRecognizer:)))
view.addGestureRecognizer(tapGesture)
}
#objc func viewTapped(gestureRecognizer: UITapGestureRecognizer) {
view.endEditing(true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.searchBar_shop.resignFirstResponder()
}
func createArray(completion: #escaping ([ShopCell]) -> () ) {
var tempShopCells: [ShopCell] = []
let rootRef = Database.database().reference()
let query = rootRef.child("tobaccos").queryOrdered(byChild: "name")
query.observeSingleEvent(of: .value) { (snapshot) in
let dispatchGroup = DispatchGroup()
for child in snapshot.children.allObjects as! [DataSnapshot] {
let value = child.value as? [String: Any];
let name = value?["name"] as? String ?? "";
let brand = value?["brand"] as? String ?? "";
let iD = value?["iD"] as? String ?? "";
dispatchGroup.enter()
let imageReference = Storage.storage().reference().child("tobaccoPictures").child("\(iD).jpg")
imageReference.getData(maxSize: (1 * 1024 * 1024)) { (data, error) in
if let _error = error{
print(_error)
} else {
if let _data = data {
let image: UIImage! = UIImage(data: _data)
tempShopCells.append(ShopCell(productName: name, brandName: brand, productImage: image, iD: iD))
}
}
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .main) {
completion(tempShopCells)
}
}
}
}
extension ShopViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.ShopCells.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let shopCell = ShopCells[indexPath.row]
let cell = tableView_shop.dequeueReusableCell(withIdentifier: "ShopCell") as! ShopTableViewCell
cell.setShopCell(shopCell: shopCell)
return cell
}
}
I have now tried everything (as far as I know), I even made the whole thing from scratch, but it still doesn´t work.
I have made a search bar which can search for data in firebase and display them in a tableview. If the user clicks on a profile in the search bar, a new viewcontroller shows with information about that user.
The problem is that if you start searching, then clicks on a profile, it shows the profile which started on that position in the tableview before the search happened.
This is what I see without searching, it displays the 2 profiles in firebase which is correct:
Now, when I search for the profile "Lars Larsen" it filters like it should:
However, if I now choose the profile by clicking on "Lars Larsen" it shows the profile for "Jonas Larsen", which was at the top before the search?
This is the code for my searchViewController:
import UIKit
import FirebaseDatabase
class SearchTableViewController: UITableViewController,
UISearchResultsUpdating {
let searchController = UISearchController(searchResultsController: nil)
#IBOutlet var findKunder: UITableView!
var loggedInUser: user?
var usersArray = [NSDictionary?]()
var filteredUsers = [NSDictionary?]()
var databaseRef = Database.database().reference()
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
databaseRef.child("Buyers").queryOrdered(byChild: "Personnr").observe(.childAdded, with: { (snapshot) in
let key = snapshot.key
let snapshot = snapshot.value as? NSDictionary
snapshot?.setValue(key, forKey: "Personnr")
self.usersArray.append(snapshot)
//Insert rows
self.findKunder.insertRows(at: [IndexPath(row:self.usersArray.count-1,section:0)], with: UITableViewRowAnimation.automatic)
}) { (error) in
print(error)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if searchController.isActive && searchController.searchBar.text != ""{
return filteredUsers.count
}
return self.usersArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let user : NSDictionary?
if searchController.isActive && searchController.searchBar.text != ""{
user = filteredUsers[indexPath.row]
}
else
{
user = self.usersArray[indexPath.row]
}
cell.textLabel?.text = user? ["Navn"] as? String
cell.detailTextLabel?.text = user?["Telefonnr"] as? String
// Configure the cell...
return cell
}
func updateSearchResults(for searchController: UISearchController) {
filterContent(searchText: self.searchController.searchBar.text!)
}
func filterContent(searchText:String)
{
self.filteredUsers = self.usersArray.filter{ user in
var fNavn = false
var personNr = false
var searchBil = false
var telefonNr = false
var korekortNr = false
if let Navn = user!["Navn"] as? String {
fNavn = Navn.lowercased().contains(searchText.lowercased())
}
if let Bil = user!["Bil"] as? String {
searchBil = Bil.lowercased().contains(searchText.lowercased())
}
if let Personnr = user!["Personnr"] as? String {
personNr = Personnr.lowercased().contains(searchText.lowercased())
}
if let Kørekortnr = user!["Kørekortnr"] as? String {
korekortNr = Kørekortnr.lowercased().contains(searchText.lowercased())
}
if let Telefonnr = user!["Telefonnr"] as? String {
telefonNr = Telefonnr.lowercased().contains(searchText.lowercased())
}
return fNavn || personNr || searchBil || korekortNr || telefonNr
}
tableView.reloadData()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let showUserProfileViewController = segue.destination as! userProfileViewController
showUserProfileViewController.loggedInUser = self.loggedInUser
if let indexPath = tableView.indexPathForSelectedRow {
let user = usersArray[indexPath.row]
showUserProfileViewController.otherUser = user
}
}
}
This is the code I use to show the profiles:
import UIKit
import Firebase
class ProfileViewController: UIViewController {
//Outlets
var loggedInUser:User?
var otherUser:NSDictionary?
var databaseRef:DatabaseReference!
var loggedInUserData: NSDictionary?
#IBOutlet weak var Biler: UILabel!
#IBOutlet weak var Navn: UILabel!
#IBOutlet weak var kundeInfo: UILabel!
#IBOutlet weak var bilInfo: UILabel!
#IBOutlet weak var telefonNr: UILabel!
#IBOutlet weak var korekortNr: UILabel!
#IBOutlet weak var personNr: UILabel!
#IBOutlet weak var Interesse: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.databaseRef = Database.database().reference()
databaseRef.child("Buyers").child(self.otherUser?["Personnr"] as! String).observe(.value, with: { (snapshot) in
let uid = self.otherUser?["Personnr"] as! String
self.otherUser = snapshot.value as? NSDictionary
self.otherUser?.setValue(uid, forKey: "Personnr")
self.Navn.text = self.otherUser?["Navn"] as? String
self.bilInfo.text = self.otherUser?["Bil"] as? String
self.telefonNr.text = self.otherUser?["Telefonnr"] as? String
self.Interesse.text = self.otherUser?["Interesse"] as? String
self.personNr.text = self.otherUser?["Personnr"] as? String
self.korekortNr.text = self.otherUser?["Kørekortnr"] as? String
}
// Do any additional setup after loading the view.
)}
Please let me know if you need any other information. I hope you can help.
If the search bar is active and it does contain text, you should pass a user to ProfileViewController from the filteredUsers array and not usersArray.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
[...]
if let indexPath = tableView.indexPathForSelectedRow {
if searchController.isActive && searchController.searchBar.text != "" {
showUserProfileViewController.otherUser = filteredUsers[indexPath.row]
} else {
showUserProfileViewController.otherUser = usersArray[indexPath.row]
}
}
}
On a side note, you shouldn't us NSDictionary in Swift. Use Swift's Dictionary instead (for your case, if would be [String: Any]).
If I'm understanding your code correctly, your issue is here:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let showUserProfileViewController = segue.destination as! userProfileViewController
showUserProfileViewController.loggedInUser = self.loggedInUser
if let indexPath = tableView.indexPathForSelectedRow {
let user = usersArray[indexPath.row]
showUserProfileViewController.otherUser = user
}
}
let user = usersArray[indexPath.row] // this is wrong
Since you filtered the results if the search bar is active you have to use your updated datasource
let user = filteredUsers[indexPath.row]
Basically, you're passing the wrong information before you segue.
I find myself stuck upon the implementation of a model for getting data from a firebase database.
I'm not sure what I've done so far is correct but as far as my knowledge of swift is concerned (I'm new to swift) I think I've followed the right path.
So I have a collection view which get the data from a firebase database.
The database structure is like so:
-SwimManager
--SwimmingPools
---SwimPoolName 1
-----Capacity: "2000"
-----PhotoUrl: "https//www.test"
---SwimPoolName 2
-----Capacity: "3000"
-----PhotoUrl: "https//www.test"
I'll show the code for the view controller, the model and the cell.
Here's my ViewController:
#IBOutlet weak var collectionView: UICollectionView!
var swimRef = Database.database().reference().child("SwimmingPools")
var swimmingPools = [SwimmingPool]()
verride func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
getSwimPoolInfo()
}
func getSwimPoolInfo() {
fishRef.observeSingleEvent(of: .value) { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let swimNameFb = snap.key
let value = snap.value
let swim = Fish(swimName: swimNameFb, photoUrl: "")
self.swimmingPools.append(swim)
// Not sure how to add the picture
}
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SwimCell", for: indexPath) as? SwimCell {
let swim: SwimminPool!
swim = swimmingPools[indexPath.row]
cell.configureCell(swim)
return cell
} else {
return UICollectionViewCell()
Model:
class SwimmingPool {
private var _swimName: String!
private var _photourl: String!
private var _capacity: String!
var swimName: String {
if _swimName == nil {
_swimName = ""
}
return _swimName
}
...............
init(swimName: String, photoUrl: String) {
self._SwimName = swimName
self._photourl = photoUrl
}
func getData() {
//perform action the get the data from the single swimmingPool (e.g. swimPoolName 1)
}
}
And finally, here's the cell:
class SwimCell: UICollectionViewCell {
#IBOutlet weak var swimThumb: UIImageView!
#IBOutlet weak var swimNameLbl: UILabel!
var swim: SwimmingPool!
func configureCell(_ swim: SwimmingPool) {
self.swim = swim
swimNameLbl.text = self.swim.swimName.capitalized
var url = URL(string: self.swim.photoUrl)
if url == nil {
url = URL(string: "")
}
swimThumb.sd_setImage(with: url)
}
}
In the Viewcontroller the func getSwimPooInfo is triggered after viewDidLoad and so the array swimminPools is empty... Honestly it seems I cannot figure where my mistake is....
Thx!