The snapshot is not represented correctly - ios

This is the code responsible for uploading text of a post for a blogging app the text of the post is retrieved correctly and saved in snapshot
struct postt {
let username : String!
let textofpost : String!
}
class TableViewController: UITableViewController {
var databaseref = FIRDatabase.database().reference()
var loggedinuser : AnyObject?
var posts = [postt]()
override func viewDidLoad() {
super.viewDidLoad()
self.loggedinuser = FIRAuth.auth()?.currentUser
self.databaseref.child("users").child(self.loggedinuser!.uid).observeSingle
Event(of: .value) {(snapshot:FIRDataSnapshot) in
let snapshot = snapshot.value as! [String:AnyObject]
let username = snapshot["name"] as? String
self.databaseref.child("posts").queryOrderedByKey().observe(.childAdded, with: {( snapshot: FIRDataSnapshot) in
let snapshot = snapshot.value as? NSDictionary
The next variable textofpost doesn't contain anything and i don't know what is the problem so when i represent the cell only the label appears which has a snapshot from the path name in the node users
let textofpost = snapshot?["text"] as? String
self.posts.insert(postt(username : username, textofpost : textofpost), at: 0)
// self.feeds.reloadData()
self.tableView.reloadData()
}
)}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let label = cell.viewWithTag(1) as! UILabel
label.text = posts[indexPath.row].username
let textview = cell.viewWithTag(2) as! UITextView
textview.text = posts[indexPath.row].textofpost
return cell
}
}

Related

Swift Table View Cell Changing Data

I have table view controller. My problem; The cell in my table view changes every time I enter the view controller. For example; There are 2 data (address-1 and address-2). The first row is address-1, the second row is address-2, when I re-enter the page, the cells change. How can I fix this problem. Thanks
import UIKit
import Firebase
import MapKit
class DenemeTableViewController: UITableViewController {
var ref: DatabaseReference!
let user: User = Auth.auth().currentUser!
var adresListesi = [Adresler]()
var adres: Adresler!
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.table.delegate = self
self.table.dataSource = self
Adresdefteri()
}
override func viewWillAppear(_ animated: Bool) {
Adresdefteri()
table.reloadData()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return adresListesi.count
}
//prob.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DenemeTableViewCell
let adresList = self.adresListesi[indexPath.row]
cell.textLabel?.text = adresList.adresname
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:IndexPath) {
self.performSegue(withIdentifier: "DENEMEHARİTAGO", sender: indexPath.row)
}
func Adresdefteri() {
ref = Database.database().reference()
let adreslerim = ref
adreslerim?.child("locations").child(user.emailWithoutSpecialCharacters).child("Adresler").observe( .value) { [self] (snapshot) in
if let gelenVeributunu = snapshot.value as? [String:AnyObject]{
self.adresListesi.removeAll()
for gelenSatirVerisi in gelenVeributunu {
if let sozluk = gelenSatirVerisi.value as? NSDictionary {
let key = gelenSatirVerisi.key
let adresname = sozluk["adresname"] as? String ?? ""
let latitude = sozluk["latitude"] as? Double ?? 0.0
let longitude = sozluk["longitude"] as? Double ?? 0.0
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let adres = Adresler(adresname: adresname, latitude: latitude, longitude: longitude, adresid: key)
self.adresListesi.append(adres)
}
}
DispatchQueue.main.async {
self.table.reloadData()
}
}
}
tableview
Sort the data source array after creating it and reloading the table view, that way it stays consistent. Cheers!
self.arrayName = arrayName.sorted(by: { $0.valueToSortByInArray > $1.valueToSortByInArray })
You just have to sort the adresListesti to make sure the order is consistent.
An example would be:
adresListesi.sort { $0.adresname < $02.adresname }
Put that right before DispatchQueue.main.async and it should work.

How to Sort TableViewCells by date string

As shown below I want to sort my TableViewCells by the date. For this I have the time which is also called timestampName.
Right before I reload the data, I tried to sort it, but somehow this has no effect. It also throws me a warning, that I dont use the result of the sorted by. I understand this, but I dont know how to fix that.
import UIKit
import Firebase
class popularViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet var table: UITableView!
// var models = [PhotoPost]()
var texttt = [TextPost]()
override func viewDidLoad() {
super.viewDidLoad()
gettingPosts()
table.register(popularTableViewCell.nib(), forCellReuseIdentifier: popularTableViewCell.identifier)
table.register(featuredTableViewCell.nib(), forCellReuseIdentifier: featuredTableViewCell.identifier)
table.register(textTableViewCell.nib(), forCellReuseIdentifier: textTableViewCell.identifier)
table.delegate = self
table.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return texttt.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
cell.configure(with: self.texttt[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 300
}
func gettingPosts(){
let db = Firestore.firestore()
let postsRef = db.collection("posts")
postsRef.addSnapshotListener { (querySnapshot, error) in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added){
let data = diff.document.data()
let Name = data["username"] as! String
let text = data["description"] as! String
let likes = data["likes"] as! Int
let typ = data["postType"] as! Int
let pfp = data["profileImage"] as! String
let uid = data["uid"] as! String
let pic = data["picture"]
let time = data["time"] as! String
if typ == 0{ // Text post
let dasDing = TextPost(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, textName: text)
self.texttt.append(dasDing)
self.texttt.sorted(by: { $0.timestampName < $1.timestampName }) //WARNING: Result of call to 'sorted(by:)' is unused
self.table.reloadData()
}
struct TextPost {
let numberOfComments: Int
let username: String
let timestampName: String
let userImageName: String
let textName: String
}
Use sort instead of sorted. The sorted method returns a new sorted array, on the other hand, the sort method sorts the array on which it was called.
self.texttt.sort(by: { $0.timestampName < $1.timestampName })
This should also work, using sorted:
self.texttt = self.texttt.sorted(by: { $0.timestampName < $1.timestampName })

Tapped cell in UITableView returns label text from last cell out of an array not the chosen one

I have fixed my earlier problem and have now worked out where the main problem is, I am pulling in a json array with alamofire but am not sure how to properly move the data from one viewcontroller to another. If I hardcode the array with var name = ["Hello", "Goodbye"] I can get it to work but am not sure how to do it with the json. Thank you to any and all help.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let URL_GET_DATA = "http://www.localnewsplus.com.au/ios/service.php"
#IBOutlet weak var tableViewHeroes: UITableView!
var heroes = [Hero]()
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return heroes.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
let hero: Hero
hero = heroes[indexPath.row]
cell.labelName.text = hero.name
cell.labelTeam.text = hero.team
Alamofire.request(hero.imageUrl!).responseImage { response in
if let image = response.result.value {
cell.heroImage.image = image
}
}
//cell.labelName.text = name[indexPath.row]
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(URL_GET_DATA).responseJSON { response in
if let json = response.result.value {
let heroesArray : NSArray = json as! NSArray
for i in 0..<heroesArray.count{
self.heroes.append(Hero(
name: (heroesArray[i] as AnyObject).value(forKey: "st_heading") as? String,
team: (heroesArray[i] as AnyObject).value(forKey: "st_modified") as? String,
imageUrl: (heroesArray[i] as AnyObject).value(forKey: "imageurl") as? String
))
}
self.tableViewHeroes.reloadData()
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "articleViewController") as? articleViewController
vc?.article_st_heading = name[indexPath.row]
self.navigationController?.pushViewController(vc!, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
There are 2 ways to do this
Try to get data from the array which you used in cellForRow to populate data
Let text = someArray[indexPath. Row]
Get the cell instead of the create new one in didSelect method
Let cell = table. CellForRowAt[indexPath ]
Let text = cell.text

empty tableview cell for at index path row is not called

All the tableview functions are working except cell for row index path .
The problem maybe that foods array is empty so the number for rows is 0 so the cell for row at index path is not called
#IBOutlet weak var foooods: UITableView!
var databaseref = Database.database().reference()
var img : AnyObject?
var foods = [String?]()
override func viewDidLoad() {
super.viewDidLoad()
self.databaseref.child("basic food").observe(.childAdded, with: {( snap: DataSnapshot) in
let snapp = snap.value as! [String:AnyObject]
if let x = snapp["name"] as! String? {
self.foods.insert(x, at: 0)
//self.foods.append(x)
}
})
self.foooods.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.foods.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("difufuehf")
let cell : foodsTableViewCell = tableView.dequeueReusableCell(withIdentifier: "aupa", for:indexPath) as! foodsTableViewCell
print("fufvksdfvysdgfvjdsgfdsygfvds,jhvjsdvsdjvguydsfgdsylfgdsyfgsdlygfsiygf")
if let foo = foods[indexPath.row] {
print(foo)
cell.food.text = foo
}
return cell
}
This must be a duplicate but I can't find one.
Your issue is that you call reloadData in the wrong place which results in it being called far too soon. You need to call it inside the completion block, after you update your data model.
And you need to make sure it gets called on the main queue.
override func viewDidLoad() {
super.viewDidLoad()
self.databaseref.child("basic food").observe(.childAdded, with: {( snap: DataSnapshot) in
if let snapp = snap.value as? [String:Any], let x = snapp["name"] as? String {
self.foods.insert(x, at: 0)
//self.foods.append(x)
DispatchQueue.main.async {
self.foooods.reloadData()
}
}
})
}
Note that I also fixed the way the value is obtained. You really need to avoid force unwrapping and force casting.

Firebase + Swift TableView Sorted by Dates

I am fairly new to realm of coding and I know this question might have been answered similarly elsewhere but when it comes to Firebase it may not. I was following this answer (Adding sections, separated by dates, to UITableView in Swift) but encounters complication when I implement .ChildAdded and insertRowAtIndexPath. My code as follows:
var ref: FIRDatabaseReference!
var mileageDatabase: [FIRDataSnapshot]! = []
var retrieveDates: [(String)] = []
var uniqueDates: [(String)] = []
struct tripDataset {
let date: String
let purpose: String
}
var tripItems = Dictionary<String, Array<tripDataset>>()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView = UITableView(frame: self.tableView.frame, style: .Grouped)
let nib = UINib(nibName: "TripTableViewCell", bundle: nil)
self.tableView.registerNib(nib, forCellReuseIdentifier: "cell")
configureDatabase()
}
func configureDatabase() {
self.ref = FIRDatabase.database().reference()
if let user = FIRAuth.auth()?.currentUser {
self.ref.child("mileage").queryOrderedByChild("user").queryEqualToValue(user.uid).observeEventType(.ChildAdded, withBlock: { (snapshot) in
self.mileageDatabase.insert(snapshot, atIndex: 0)
let snapValues = snapshot.value as! Dictionary< String, AnyObject>
let snapDates = snapValues["date"] as! String
let snapPurpose = snapValues["purpose"] as! String
self.retrieveDates.append(snapValues["date"] as! String)
self.uniqueDates = Array(Set(self.retrieveDates))
if self.tripItems.indexForKey(snapDates) == nil {
self.tripItems[snapDates] = [tripDataset(date: snapDates, purpose: snapPurpose)]
} else {
self.tripItems[snapDates]!.append(tripDataset(date: snapDates, purpose: snapPurpose))
}
self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Automatic) //Stuck hereeee.....
})
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.uniqueDates.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tripItems[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TripTableViewCell
cell.dateTimeLabel.text = self.uniqueDates(indexPath.section)
cell.purposeLabel.text = self.tripItem[self.uniqueDates(indexPath.section)]["purpose"]
return cell
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.uniqueDates(section)
}
I know there are many errors here, is there anyone who can direct me accordingly? All the async nature of Firebase just complicates the flow for me.
try this .
Change below code from
self.retrieveDates.append(snapValues["date"] as! String)
to
self.retrieveDates.insert( snapValues, at : 0)

Resources