How to retrieve data from Firebase to TableViewCell - ios

I'm working on simple program - I create objects of products and then I count their calories.
I want to get all my product in TableViewController
I've created a method, allowing me to save data properly in Firebase, but I got stuck while retrieving them to cell. I got no mistakes, but I don't have any results as well
import UIKit
import Firebase
class MainTableViewController: UITableViewController {
var products = [Products]()
override func viewDidLoad() {
super.viewDidLoad()
DataService.dataService.PRODUCT_BASE.observeEventType(.Value, withBlock: { snapshot in
print(snapshot.value)
self.products = []
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let product = Products(key: key, dictionary: postDictionary)
}
}
}
self.tableView.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(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
return products.count
}
override func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ProductCell") as! UITableViewCell?
let ProductItem = products[indexPath.row]
cell?.textLabel?.text = ProductItem.productName
cell?.detailTextLabel?.text = String(ProductItem.productCalories)
return cell!
}
This is my DataService file:
import Foundation
import Firebase
let URL_BASE = FIRDatabase.database().reference()
class DataService {
static let dataService = DataService()
private var _REF_BASE = URL_BASE
private var _USER_BASE = URL_BASE.child("users")
private var _PRODUCЕ_BASE = URL_BASE.child("products")
var REF_BASE: FIRDatabaseReference {
return _REF_BASE
}
var USER_BASE: FIRDatabaseReference {
return _USER_BASE
}
var PRODUCT_BASE: FIRDatabaseReference {
return _PRODUCЕ_BASE
}
var CURRENT_USER_REF: FIRDatabaseReference {
let userID = NSUserDefaults.standardUserDefaults().valueForKey("uid") as! String
let currentUser = URL_BASE.child("users").child(userID)
return currentUser
}
func CreateNewProduct(product: Dictionary<String, AnyObject>) {
let ProductNewRef = DataService.dataService.PRODUCT_BASE.childByAutoId()
ProductNewRef.setValue(product)
}
I can't get what I'm doing wrong. All products are represented as a dictionary.
import Foundation
import Firebase
class Products {
private var _productName: String!
private var _productCalories: Int!
var productName: String {
return _productName
}
var productCalories: Int {
return _productCalories
}
init(key: String, dictionary: Dictionary<String, AnyObject>) {
if let calories = dictionary["calories"] as? Int {
self._productCalories = calories
}
if let name = dictionary["name"] as? String {
self._productName = name
}
}
}

You intilized the
var products = [Products]()
But not adding any items from firebase callback
if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let product = Products(key: key, dictionary: postDictionary)
}
please add self.products.append(product)
if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let product = Products(key: key, dictionary: postDictionary)
self.products.append(product)
}

Related

How to check and delete duplicates values in TableView?

I have a database on Firebase and a tableview.
I have a list of brands, models, and year for motorcycles and I want to retrieve the list of brands on the tableview.
The problem is the DB has duplicates values. There is more than one motorcycle from Suzuki, there is more one models of SV 650, etc.
How can I check duplicates values, put it in a new array, and retrieve it in the tableview?
This is my TableViewController file:
import UIKit
import FirebaseAuth
import FirebaseDatabase
class SelectionMarqueViewController: UITableViewController {
var posts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
loadMarques()
}
func loadMarques() {
var ref : DatabaseReference?
ref = Database.database(url: "https://myride-test.firebaseio.com/").reference()
ref?.observe(.childAdded, with: { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
let MarqueText = dict["Marque"] as! String
let post = Post(MarqueText: MarqueText)
self.posts.append(post)
print(self.posts)
self.tableView.reloadData()
}
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath)
cell.textLabel?.text = posts[indexPath.row].Marque
return cell
}
}
And this one is the file with the Post func:
import Foundation
class Post {
var Marque: String
init(MarqueText: String) {
Marque = MarqueText
}
}
Here my Firebase Database:
Actually the tableview shows the complete list of brands in the DB, and so, many times the same brands.
On the DB and code:
"Marque" correspond to the brand.
You can implement Hashable
class Post : Hashable {
var marque: String
init(marqueText: String) {
marque = marqueText
}
// Equatable for contains
static func == (lhs:Post,rhs:Post) -> Bool {
return lhs.marque == rhs.marque
}
// Hashable for Set
var hashValue:Int {
return marque.hashValue
}
}
and use
if let dict = snapshot.value as? [String: Any] {
let MarqueText = dict["Marque"] as! String
let post = Post(MarqueText: MarqueText)
self.posts.append(post)
self.posts = Array(Set(self.posts))
print(self.posts)
self.tableView.reloadData()
}
Or simply
let marqueText = dict["Marque"] as! String
if !self.posts.map { $0.marqueText}.contains(marqueText) {
let post = Post(marqueText:marqueText)
self.posts.append(post)
self.tableView.reloadData()
}
Check and append if the marque is not available in the datasource of the tableview.
func appendMarqueAndReloadIfNeeded(_ marque: String) {
if self.posts.map({ $0.Marque }).contains(marque) {
// Do nothing
} else {
self.posts.append(Post(MarqueText: marque))
self.tableView.reloadData()
}
}
Then you call it inside observe:
///....
if let dict = snapshot.value as? [String: Any] {
let MarqueText = dict["Marque"] as! String
self.appendMarqueAndReloadIfNeeded(MarqueText)
}
///....

Swift Firebase "Cannot assign value of type 'Information' to type 'NSDictionary?'"

I have a tableview that is being populated with who a user is following. Problem is that I need to pass that cells data to "var otherUser: NSDictionary!" but because I am populating the cell using a data structure file called "Information" I get this error - "Cannot assign value of type 'Information' to type 'NSDictionary?'" in the prepareForSegue. I am unsure if I can repackage the information I need into a NSDictionary so I can successfully do a data pass. I just don't know if this is a easy solution or an actual problem because of my ignorance.
Following TableViewController Code
import UIKit
import Firebase
class BusinessFollowing: UITableViewController {
#IBOutlet var noDataView: UIView!
#IBOutlet var followingTableView: UITableView!
var yourFollowing = [Information]()
var listFollowing = [NSDictionary?]()
var databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
var loggedInUser = Auth.auth().currentUser
var loggedInUserData:NSDictionary?
var following = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.followingTableView.backgroundView = nil
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.followingTableView.reloadData()
self.yourFollowing.removeAll()
self.following.removeAll()
getFollowingData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "following" {
// gotta check if we're currently searching
if let indexPath = followingTableView.indexPathForSelectedRow {
let user = self.yourFollowing[indexPath.row]
let controller = segue.destination as? ExploreBusinessProfileSwitchView
controller?.otherUser = user
}
}
}
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
return self.yourFollowing.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! BusinessFollowingCell
let following = yourFollowing[indexPath.row]
let businessName = following.businessName
let businessStreet = following.businessStreet
let businessCity = following.businessCity
let businessState = following.businessState
cell.businessName.text = businessName
cell.businessStreet.text = businessStreet
cell.businessCity.text = businessCity
cell.businessState.text = businessState
// cell.businessName?.text = self.listFollowing[indexPath.row]?["businessName"] as? String
// cell.businessStreet?.text = self.listFollowing[indexPath.row]?["businessStreet"] as? String
// cell.businessCity?.text = self.listFollowing[indexPath.row]?["businessCity"] as? String
// cell.businessState?.text = self.listFollowing[indexPath.row]?["businessState"] as? String
return cell
}
func getFollowingData() {
self.yourFollowing.removeAll()
self.following.removeAll()
self.followingTableView.reloadData()
Database.database().reference().child("Businesses").child((loggedInUser?.uid)!).child("following").observe(.value, with: { snapshot in
if snapshot.exists() {
MBProgressHUD.showAdded(to: self.view, animated: true)
let databaseRef = Database.database().reference()
databaseRef.child("Businesses").queryOrderedByKey().observeSingleEvent(of: .value, with: { (usersSnapshot) in
let users = usersSnapshot.value as! [String: AnyObject]
for (_, value) in users {
if let userID = value["uid"] as? String {
if userID == Auth.auth().currentUser?.uid {
print(value)
if let followingUsers = value["following"] as? [String : String] {
for (_,user) in followingUsers {
self.following.append(user)
}
}
databaseRef.child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { (postsSnapshot) in
let posts = postsSnapshot.value as! [String: AnyObject]
for (_, post) in posts {
for (_, postInfo) in post as! [String: AnyObject] {
if let followingID = postInfo["uid"] as? String {
for each in self.following {
if each == followingID {
guard let uid = postInfo["uid"] as! String? else {return}
guard let name = postInfo["businessName"] as! String? else {return}
guard let address = postInfo["businessStreet"] as! String? else {return}
guard let state = postInfo["businessState"] as! String? else {return}
guard let city = postInfo["businessCity"] as! String? else {return}
self.yourFollowing.append(Information(uid: uid, businessName: name, businessStreet: address, businessCity: city, businessState: state))
}
self.followingTableView.backgroundView = nil
self.followingTableView.reloadData()
}
}
}
}
MBProgressHUD.hide(for: self.view, animated: true)
}) { (error) in
print(error.localizedDescription)
}
}
}
}
})
} else {
print("Not following anyone")
self.followingTableView.backgroundView = self.noDataView
MBProgressHUD.hide(for: self.view, animated: true)
}
})
}
}
"Information" Data Structure File
import UIKit
class Information {
var uid: String
var businessName: String
var businessStreet: String
var businessCity: String
var businessState: String
init(uid: String, businessName: String, businessStreet: String, businessCity: String, businessState: String){
self.uid = uid
self.businessName = businessName
self.businessStreet = businessStreet
self.businessCity = businessCity
self.businessState = businessState
}
}
The error is pretty clear.
user in ExploreBusinessProfileSwitchView is obviously declared as NSDictionary, declare it as Information.
By the way don't use NSArray / NSDictionary in Swift. Use native types.

How to display a multidimensional array under different sections in swift 3

I have been trying to create multidimensional arrays and display each array under each section .. but I keep ending up with a fatal error index out of range . The code that i display below is how I access my firebase data and print each array from the database.. issue is I get the data I assign an array to it create it but can’t seem to display it due to the error . Hope someone helps for reference regarding the error I have attached a screenshot as well.
#IBOutlet weak var tableview: UITableView!
var yourArray = [String]()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var sundaycoursenamearray = [String]()
var sundaycoursecodearray = [String]()
var sundaycourselocationarray = [String]()
var sundayfromarray = [String]()
var sundaytoarray = [String]()
var mondaycoursenamearray = [String]()
var mondaycoursecodearray = [String]()
var mondaycourselocationarray = [String]()
var mondayfromarray = [String]()
var mondaytoarray = [String]()
var tuesdaycoursenamearray = [String]()
var tuesdaycoursecodearray = [String]()
var tuesdaycourselocationarray = [String]()
var tuesdayfromarray = [String]()
var tuesdaytoarray = [String]()
var wednesdaycoursenamearray = [String]()
var wednesdaycoursecodearray = [String]()
var wednesdaycourselocationarray = [String]()
var wednesdayfromarray = [String]()
var wednesdaytoarray = [String]()
var thursdaycoursenamearray = [String]()
var thursdaycoursecodearray = [String]()
var thursdaycourselocationarray = [String]()
var thursdayfromarray = [String]()
var thursdaytoarray = [String]()
var fridaycoursenamearray = [String]()
var fridaycoursecodearray = [String]()
var fridaycourselocationarray = [String]()
var fridayfromarray = [String]()
var fridaytoarray = [String]()
var saturdaycoursenamearray = [String]()
var saturdaycoursecodearray = [String]()
var saturdaycourselocationarray = [String]()
var saturdayfromarray = [String]()
var saturdaytoarray = [String]()
var coursecodes = [[String]]()
var coursenames = [[String]]()
var courselocations = [[String]]()
var fromtimes = [[String]]()
var totimes = [[String]]()
var days = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
override func viewWillAppear(_ animated: Bool) {
let uid = Auth.auth().currentUser?.uid
if(uid == nil){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nextviewController = storyboard.instantiateViewController(withIdentifier: "loginscreen")
//self.present(profileViewController, animated: true, completion: nil)
self.present(nextviewController, animated: true, completion: nil)
}
for j in days {
for i in 1 ..< 10 {
let ref1 = Database.database().reference().child("users").child((uid)!).child("courses").child(j).child(String(i))
ref1.observeSingleEvent(of: .value, with: { snapshot in
if let dictionary = snapshot.value as? [String: AnyObject] {
// print(dictionary)
if j == "Sunday" {
if let points = dictionary["coursname"] as? String {
self.sundaycoursecodearray.append(points)
print(self.sundaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.sundaycoursenamearray.append(points1)
print(self.sundaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.sundaycourselocationarray.append(points1)
print(self.sundaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.sundayfromarray.append(points1)
print(self.sundayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.sundaytoarray.append(points1)
print(self.sundaytoarray)
}
}
if j == "Monday" {
if let points = dictionary["coursname"] as? String {
self.mondaycoursecodearray.append(points)
print(self.mondaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.mondaycoursenamearray.append(points1)
print(self.mondaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.mondaycourselocationarray.append(points1)
print(self.mondaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.mondayfromarray.append(points1)
print(self.mondayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.mondaytoarray.append(points1)
print(self.mondaytoarray)
}
}
if j == "Tuesday" {
if let points = dictionary["coursname"] as? String {
self.tuesdaycoursecodearray.append(points)
print(self.tuesdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.tuesdaycoursenamearray.append(points1)
print(self.tuesdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.tuesdaycourselocationarray.append(points1)
print(self.tuesdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.tuesdayfromarray.append(points1)
print(self.tuesdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.tuesdaytoarray.append(points1)
print(self.tuesdaytoarray)
}
}
if j == "Wednesday" {
if let points = dictionary["coursname"] as? String {
self.wednesdaycoursecodearray.append(points)
print(self.wednesdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.wednesdaycoursenamearray.append(points1)
print(self.wednesdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.wednesdaycourselocationarray.append(points1)
print(self.wednesdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.wednesdayfromarray.append(points1)
print(self.wednesdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.wednesdaytoarray.append(points1)
print(self.wednesdaytoarray)
}
}
if j == "Thursday" {
if let points = dictionary["coursname"] as? String {
self.thursdaycoursecodearray.append(points)
print(self.thursdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.thursdaycoursenamearray.append(points1)
print(self.thursdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.thursdaycourselocationarray.append(points1)
print(self.thursdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.thursdayfromarray.append(points1)
print(self.thursdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.thursdaytoarray.append(points1)
print(self.thursdaytoarray)
}
}
if j == "Friday" {
if let points = dictionary["coursname"] as? String {
self.fridaycoursecodearray.append(points)
print(self.fridaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.fridaycoursenamearray.append(points1)
print(self.fridaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.fridaycourselocationarray.append(points1)
print(self.fridaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.fridayfromarray.append(points1)
print(self.fridayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.fridaytoarray.append(points1)
print(self.fridaytoarray)
}
}
if j == "Saturday" {
if let points = dictionary["coursname"] as? String {
self.saturdaycoursecodearray.append(points)
print(self.saturdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.saturdaycoursenamearray.append(points1)
print(self.saturdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.saturdaycourselocationarray.append(points1)
print(self.saturdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.saturdayfromarray.append(points1)
print(self.saturdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.saturdaytoarray.append(points1)
print(self.saturdaytoarray)
}
}
self.coursecodes.append(self.sundaycoursenamearray)
self.coursecodes.append(self.mondaycoursenamearray)
self.coursecodes.append(self.tuesdaycoursenamearray)
self.coursecodes.append(self.wednesdaycoursenamearray)
self.coursecodes.append(self.thursdaycoursenamearray)
self.coursecodes.append(self.fridaycoursenamearray)
self.coursecodes.append(self.saturdaycoursenamearray)
self.coursenames.append(self.sundaycoursecodearray)
self.coursenames.append(self.mondaycoursecodearray)
self.coursenames.append(self.tuesdaycoursecodearray)
self.coursenames.append(self.wednesdaycoursecodearray)
self.coursenames.append(self.thursdaycoursecodearray)
self.coursenames.append(self.fridaycoursecodearray)
self.coursenames.append(self.saturdaycoursecodearray)
self.courselocations.append(self.sundaycourselocationarray)
self.courselocations.append(self.mondaycourselocationarray)
self.courselocations.append(self.tuesdaycourselocationarray)
self.courselocations.append(self.wednesdaycourselocationarray)
self.courselocations.append(self.thursdaycourselocationarray)
self.courselocations.append(self.fridaycourselocationarray)
self.courselocations.append(self.saturdaycourselocationarray)
self.fromtimes.append(self.sundayfromarray)
self.fromtimes.append(self.mondayfromarray)
self.fromtimes.append(self.tuesdayfromarray)
self.fromtimes.append(self.wednesdayfromarray)
self.fromtimes.append(self.thursdayfromarray)
self.fromtimes.append(self.fridayfromarray)
self.fromtimes.append(self.saturdayfromarray)
self.totimes.append(self.sundaytoarray)
self.totimes.append(self.mondaytoarray)
self.totimes.append(self.tuesdaytoarray)
self.totimes.append(self.wednesdaytoarray)
self.totimes.append(self.thursdaytoarray)
self.totimes.append(self.fridaytoarray)
self.totimes.append(self.saturdaytoarray)
self.tableview.reloadData()
}
})
} }
super.viewWillAppear(animated)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return days[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return days.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return coursenames[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! homeTableViewCell
// Configure the cell...
// cell.classcode?.text = sundaycoursenamearray[indexPath.section]
cell.classcode?.text = coursenames[indexPath.section][indexPath.row]
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// 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.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
You should create a model for your data then create arrays that include the model.
You can create a simple struct like so:
struct Course {
var name : String?
var code: String?
var location: String?
var toTime: String?
var fromTime: String?
}
After you create the model you can create an array that contains this type of struct.
Also for numberOfRowsInSection you don't have to use subscript. Just return:
return coursenames.count
That is why you get the error.

Iterating through all nodes in node in Firebase

I've got sample structure that looks like this:
I want to add every item to the array of items I've created. So as you can see the downloadListData function can only download information from Apples, because I don't know how to get to Apples, Bread and Eggs in the same time without writing a lot of code. I was trying loops and arrays and it didn't work. Moreovery I was analyzing examples on the Internet and I didn't get the answer which worked in my app.
ListItem.swift:
import Foundation
import Firebase
struct ListItem{
var name : String!
var addedBy : String!
var completed : Bool!
init(name: String, addedBy: String, completed: Bool){
self.name = name
self.addedBy = addedBy
self.completed = completed
}
}
part of my ViewController.swift:
import UIKit
import Firebase
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var rootRef : FIRDatabaseReference!
var listDataRef : FIRDatabaseReference!
var refHandle: UInt!
var listItemsDownload = [ListItem]()
//test vars
var user : String!
#IBOutlet weak var plusButton: UIButton!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.delegate = self
tableView.dataSource = self
user = "test#me.com"
rootRef = FIRDatabase.database().reference()
listDataRef = rootRef.child("listData")
downloadListData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listItemsDownload.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? CellData{
print("cellForRowAt")
let items = listItemsDownload[indexPath.row]
// testing the tableView
cell.nameLabel?.text = items.name
}
return cell
} else{
print("else")
return CellData()
}
}
func downloadListData(){
print(" ### DOWNLOAD ###")
self.listDataRef.observe(FIRDataEventType.value, with: { snapshot in
var downloadedName : String!
var downloadedUser : String!
var downloadedComplete : Bool!
if let dict = snapshot.value as? Dictionary<String, Any>{
if let apples = dict["Apples"] as? Dictionary<String, Any>{
if let name = apples["name"] as? String{
downloadedName = name
}
if let user = apples["addedBy"] as? String{
downloadedUser = user
}
if let completed = apples["completed"] as? Bool{
downloadedComplete = completed
}
let item = ListItem(name: downloadedName, addedBy: downloadedUser, completed: downloadedComplete)
self.listItemsDownload.append(item)
self.tableView.reloadData()
}
}
})
}
So probably I have to change only this line to get to different values and not only Apples (if let apples = dict["Apples"] as? Dictionary<String, Any>{
Just use a separate method which you can call with your different keys like this:
func downloadListData(){
print(" ### DOWNLOAD ###")
self.listDataRef.observe(FIRDataEventType.value, with: { snapshot in
addAllItemsFromSnapshotWithKey(snapshot, key: "Apples")
addAllItemsFromSnapshotWithKey(snapshot, key: "Bread")
addAllItemsFromSnapshotWithKey(snapshot, key: "Eggs")
// You need to reload your table view on the main thread, since it's an asynchronous call to firebase
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
}
func addAllItemsFromSnapshotWithKey(_ snapshot: FIRDataSnapshot, key: String) {
var downloadedName : String!
var downloadedUser : String!
var downloadedComplete : Bool!
if let dict = snapshot.value as? Dictionary<String, Any>{
if let values = dict[key] as? Dictionary<String, Any> {
if let name = values["name"] as? String{
downloadedName = name
}
if let user = values["addedBy"] as? String{
downloadedUser = user
}
if let completed = values["completed"] as? Bool{
downloadedComplete = completed
}
let item = ListItem(name: downloadedName, addedBy: downloadedUser, completed: downloadedComplete)
self.listItemsDownload.append(item)
}
}
}
Update for a more scalable solution. Just loop through all keys
func downloadListData(){
print(" ### DOWNLOAD ###")
self.listDataRef.observe(FIRDataEventType.value, with: { snapshot in
var downloadedName : String!
var downloadedUser : String!
var downloadedComplete : Bool!
if let dict = snapshot.value as? Dictionary<String, Any>{
for key in dict.keys {
if let values = dict[key] as? Dictionary<String, Any> {
if let name = values["name"] as? String{
downloadedName = name
}
if let user = values["addedBy"] as? String{
downloadedUser = user
}
if let completed = values["completed"] as? Bool{
downloadedComplete = completed
}
let item = ListItem(name: downloadedName, addedBy: downloadedUser, completed: downloadedComplete)
self.listItemsDownload.append(item)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}

Retrieving objects from firebase

I'm working on simple program - I create objects of products and then I count their calories.
I want to count sum of all calories of my products.
I've created a method, allowing me to save data properly in Firebase, but I got stuck while retrieving them:
import UIKit
import Firebase
class TotalViewController: UIViewController {
var products = [Products]()
#IBOutlet weak var calotyCounter: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
DataService.dataService.PRODUCT_BASE.observeEventType(.Value, withBlock: { snapshot in
print(snapshot.value)
self.products = []
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let product = Products(key: key, dictionary: postDictionary)
}
}
}
self.updateCalory()
})
// Do any additional setup after loading the view.
}
func updateCalory() {
var CaloryArray: [Int] = []
for product in products {
CaloryArray.append(Int(product.productCalories))
}
print (CaloryArray)
calotyCounter.text? = String(CaloryArray.reduce(0, combine: +))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
I got an empty array, instead of array of objects callory value.
Here is my model of Products.I made it through dictionary
import Foundation
import Firebase
class Products {
private var _productName: String!
private var _productCalories: Int!
var productName: String {
return _productName
}
var productCalories: Int {
return _productCalories
}
init(key: String, dictionary: Dictionary<String, AnyObject>) {
if let calories = dictionary["calories"] as? Int {
self._productCalories = calories
}
if let name = dictionary["name"] as? String {
self._productName = name
}
}
}
What I'm doing wrong?
You have only initiated the empty array of products in viewDidLoad()
self.products = []
and not assigning any thing to it anywhere. thats why you are getting the empty array.
and on updateCalory() method you are looping on empty array (array with zero items)
EDIT 1
you must append the product i.e
let product = Products(key: key, dictionary: postDictionary)
to your products array in loop. like this
for snap in snapshots {
if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let product = Products(key: key, dictionary: postDictionary)
self. products.append(product) // add this line
}
}

Resources