Sort TableView Cells Alphabetically using Swift - ios

I am using firebase to load data into tableview cells, and here is the structure of my data.
struct postStruct {
let title : String!
let author : String!
let bookRefCode : String!
let imageDownloadString : String!
let status : String!
let reserved : String!
let category : String!
let dueDate : String!
}
Now i need to sort the tableview cells holding the data alphabetically, with the titles starting with A at the top, and Z at the bottom.
class DirectoryTableView: UITableViewController {
var posts = [postStruct]()
override func viewDidLoad() {
let databaseRef = Database.database().reference()
databaseRef.child("Books").queryOrderedByKey().observe(.childAdded, with: {
snapshot in
var snapshotValue = snapshot.value as? NSDictionary
let title = snapshotValue!["title"] as? String
snapshotValue = snapshot.value as? NSDictionary
let author = snapshotValue!["author"] as? String
snapshotValue = snapshot.value as? NSDictionary
let bookRefCode = snapshotValue!["bookRefCode"] as? String
snapshotValue = snapshot.value as? NSDictionary
let status = snapshotValue!["status"] as? String
snapshotValue = snapshot.value as? NSDictionary
let reserved = snapshotValue!["reserved"] as? String
snapshotValue = snapshot.value as? NSDictionary
let category = snapshotValue!["category"] as? String
snapshotValue = snapshot.value as? NSDictionary
let dueDate = snapshotValue!["dueDate"] as? String
snapshotValue = snapshot.value as? NSDictionary
self.posts.insert(postStruct(title: title, author: author, bookRefCode: bookRefCode, status: status, reserved: reserved, category: category, dueDate: dueDate) , at: 0)
self.tableView.reloadData()
})
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let databaseRef = Database.database().reference()
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
let label2 = cell?.viewWithTag(2) as! UILabel
label2.text = posts[indexPath.row].author
let label3 = cell?.viewWithTag(3) as! UILabel
label3.text = posts[indexPath.row].bookRefCode
let label4 = cell?.viewWithTag(4) as! UILabel
label4.text = posts[indexPath.row].status
let label5 = cell?.viewWithTag(5) as! UILabel
label5.text = posts[indexPath.row].category
let image1 = cell?.viewWithTag(6) as! UILabel
image1.text = posts[indexPath.row].imageDownloadString
let label6 = cell?.viewWithTag(7) as! UILabel
label6.text = posts[indexPath.row].reserved
let label9 = cell?.viewWithTag(9) as! UILabel
label9.text = posts[indexPath.row].dueDate
return cell!
}
Any ideas, please help!
I have tried to sort them with different methods, but I'm confused!

As I said in my comment you don't need to sort your cells you need sort your datarsource array instead, to do that add this line self.posts.sort(by: {$0.title < $1.title}) below your self.posts.insert(postStruct(title: title, author: author, bookRefCode: bookRefCode, status: status, reserved: reserved, category: category, dueDate: dueDate) , at: 0) adding this line your posts array will keep ordered and every time you add another post will be ordered again
Your viewDidLoad full code with the sort
override func viewDidLoad() {
let databaseRef = Database.database().reference()
databaseRef.child("Books").queryOrderedByKey().observe(.childAdded, with: {
snapshot in
var snapshotValue = snapshot.value as? NSDictionary
let title = snapshotValue!["title"] as? String
snapshotValue = snapshot.value as? NSDictionary
let author = snapshotValue!["author"] as? String
snapshotValue = snapshot.value as? NSDictionary
let bookRefCode = snapshotValue!["bookRefCode"] as? String
snapshotValue = snapshot.value as? NSDictionary
let status = snapshotValue!["status"] as? String
snapshotValue = snapshot.value as? NSDictionary
let reserved = snapshotValue!["reserved"] as? String
snapshotValue = snapshot.value as? NSDictionary
let category = snapshotValue!["category"] as? String
snapshotValue = snapshot.value as? NSDictionary
let dueDate = snapshotValue!["dueDate"] as? String
snapshotValue = snapshot.value as? NSDictionary
self.posts.insert(postStruct(title: title, author: author, bookRefCode: bookRefCode, status: status, reserved: reserved, category: category, dueDate: dueDate) , at: 0)
self.posts.sort(by: {$0.title < $1.title})
self.tableView.reloadData()
})

Related

Swift firebase get data

How can I get name, quant from this structure:
Im try this:
var handle: DatabaseHandle?
var ref: DatabaseReference?
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
handle = ref?.child("Цитаты").child("Из Книг").child("Дорогой звезд").child("Quote1").observe(.childAdded, with: { (snapshot) in
let user = snapshot.value
print(user!) //text from name + 10 + Quote1
}
When I print snapshot.value it's give me data from Quote1 , but I want to show name in textField and quant in label I try this:
ref = Database.database().reference()
handle = ref?.child("Цитаты").child("Из Книг").child("Дорогой звезд").child("Quote1").observe(.childAdded, with: { (snapshot) in
let user = snapshot.value
if let us = user!["name"] as? String {
if let quant = user!["quant"] as? String{
self.quoteTextField.text = us
self.quotelabel.text = quant
}
}
And have error. How can I add data from snapshot.value to label and textField?
As I was checking your screen, quant is an Int not String, so try this
ref = Database.database().reference()
handle = ref?.child("Цитаты").child("Из Книг").child("Дорогой звезд").child("Quote1").observe(.childAdded, with: { (snapshot) in
//let username = snapshot.value as? NSDictionary
let user = snapshot.value as? [String: Any]
if let us = user!["name"] as? String {
if let quant = user!["quant"] as? Int {
self.quoteTextField.text = us
self.quotelabel.text = quant.description
}
}
}
You need to cast the snapshot.value as a dictionary -
let user = snapshot.value as? NSDictionary
You should also consider safely unwrapping your optionals -
let name = user?["name"] as? String ?? ""
let quant = user?["quant"] as? Int ?? 0

manually entered data in firebase issue

I am manually entering in data into my database and the only variable not getting passed from my database is the author and I do not know where I am going wrong.
func getAllArticles(handler: #escaping (_ articles: [Article])-> ()){
var articleArray = [Article]()
REF_ARTICLES.observeSingleEvent(of: .value) { (articleMessageSnapshot) in
guard let articleMessageSnapshot = articleMessageSnapshot.children.allObjects as? [DataSnapshot] else {return}
for article in articleMessageSnapshot {
let content = article.childSnapshot(forPath: "content").value as? String ?? "no content"
let author = article.childSnapshot(forPath: "author").value as? String ?? "no author"
let twitterHandle = article.childSnapshot(forPath: "twitterHandle").value as? String ?? "none"
let articleTitle = article.childSnapshot(forPath: "articleTitle").value as? String ?? "no title"
let date = article.childSnapshot(forPath: "date").value as? String ?? "no date"
let article = Article(content: content, author: author, twitterHandle: twitterHandle, ArticleTitle: articleTitle, date: date)
articleArray.append(article)
}
handler(articleArray)
}
}
Please check out below code
var articleArray = [Article]()
//REF_ARTICLES
let ref = Database.database().reference().child(“articles”)
ref.observe(.childAdded, with: { (snapshot) in
print(snapshot)
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
let articleObj = Article()
articleObj.Content = dictionary["content"] as? String
articleObj.Author = dictionary["author"] as? String
articleObj.Twitterhandle = dictionary["twitterHandle"] as? String
articleObj.Title = dictionary["articleTitle"] as? String
articleObj.Date = dictionary["date"] as? String
self. articleArray.append(articleObj)
}, withCancel: nil)
}
I am also working on similar app where i am storing data to firebase and retrieving. Below approach i used to fetch the data from firebase database. Please try once.
func getAllArticles(handler: #escaping (_ articles: [Article])-> ()) {
Database.database().reference().child("Articles").observe(.childAdded, with: { (snapshot) in
print("articles = \(snapshot)")
if let dict = snapshot.value as? [String: Any] {
let article = Article()
article.articleTitle = dict["articleTitle"] as? String
article.author = dict["author"] as? String
article.twitterHandle = dict["twitterHandle"] as? String
article.date = dict["date"] as? String
article.content = dict["content"] as? String
self.articleArray.append(article)
}
handler(articleArray)
}, withCancel: nil)
}
im not sure what the underlying issue was, but i fixed it by deleting "author" from the firebase tree and then adding it back

Efficiently determine if user liked post in Firebase

I have an app where users can like posts and I want to determine if the current user has previously liked a post in an efficient manner. My data currently looks like this:
I also store the likes for every user
In my current query I am doing this:
if let people = post["peopleWhoLike"] as? [String: AnyObject] {
if people[(Auth.auth().currentUser?.uid)!] != nil {
posst.userLiked = true
}
}
However, I believe this requires me to download all of the post's likes which isn't very efficient, so I tried this:
if (post["peopleWhoLike\(Auth.auth().currentUser!.uid)"] as? [String: AnyObject]) != nil {
posst.userLiked = true
}
The second method doesn't seem to be working correctly. Is there a better way to do this?
Here is my initial query as well:
pagingReference.child("posts").queryLimited(toLast: 5).observeSingleEvent(of: .value, with: { snap in
for child in snap.children {
let child = child as? DataSnapshot
if let post = child?.value as? [String: AnyObject] {
let posst = Post()
if let author = post["author"] as? String, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String, let postDescription = post["postDescription"] as? String, let timestamp = post["timestamp"] as? Double, let category = post["category"] as? String, let table = post["group"] as? String, let userID = post["userID"] as? String, let numberOfComments = post["numberOfComments"] as? Int, let region = post["region"] as? String, let numLikes = post["likes"] as? Int {
Solved it:
In the tableView I just query for the liked value directly and then determine what button to display.
static func userLiked(postID: String, cell: BetterPostCell, indexPath: IndexPath) {
// need to cache these results so we don't query more than once
if newsfeedPosts[indexPath.row].userLiked == false {
if let uid = Auth.auth().currentUser?.uid {
likeRef.child("userActivity").child(uid).child("likes").child(postID).queryOrderedByKey().observeSingleEvent(of: .value, with: { snap in
if snap.exists() {
newsfeedPosts[indexPath.row].userLiked = true
cell.helpfulButton.isHidden = true
cell.notHelpfulButton.isHidden = false
}
})
likeRef.removeAllObservers()
}
}
}
Called in my TableView:
DatabaseFunctions.userLiked(postID: newsfeedPosts[indexPath.row].postID, cell: cell, indexPath: indexPath)

I cannot get the data from my snapshot to load into my tableView cells

ref = Database.database().reference()
ref.child("Clubs").observe(.value, with: { (snapshot : DataSnapshot) in
print("clubs: \(snapshot)")
if let childSnapshot = snapshot.value as? [String : AnyObject] {
print("myClubs: \(childSnapshot)")
From this point, i am unable to get the "name" and "bannerImage" to load into my tableView
if let clubName = childSnapshot["name"] as? String, let banner = childSnapshot["bannerImage"] as? String {
print(clubName)
print(banner)
let club = Club(name: clubName, image: banner)
print("new club success: \(club)")
self.nightClubs.append(club)
self.tableView.reloadData()
}
Use this:-
ref = Database.database().reference()
ref.child("Clubs").observe(.value, with: { (snapshot) in
print("clubs: \(snapshot)")
if(snapshot.exists()) {
let array:NSArray = snapshot.children.allObjects as NSArray
for obj in array {
let snapshot:FIRDataSnapshot = obj as! FIRDataSnapshot
if let childSnapshot = snapshot.value as? [String : AnyObject] {
print("myClubs: \(childSnapshot)")
if let clubName = childSnapshot["name"] as? String, let banner = childSnapshot["bannerImage"] as? String {
print(clubName)
print(banner)
let club = Club(name: clubName, image: banner)
print("new club success: \(club)")
self.nightClubs.append(club)
}
}
}
self.tableView.reloadData()
}
}

Firebase Query Error in Swift3: Type 'NSFastEnumerationIterator.Element' (aka 'Any') does not conform to protocol 'AnyObject'

I'm not sure how to fix this error. Can someone explain it?
Type 'NSFastEnumerationIterator.Element' (aka 'Any') does not conform to protocol 'AnyObject'
Here's my Query.
media24HourQuery.observe(FIRDataEventType.value, with: { snapshot in
var newItems = [[String: AnyObject]]()
for child in snapshot.children {
let title = (child as AnyObject).value["title"] as? String
let userID = (child as AnyObject).value["userID"] as? String
let mediaID = (child as AnyObject).value["mediaID"] as? String
let timestamp = (child as AnyObject).value["timestamp"] as? Double
edit: this doesn't work either (everything is nil)
for _ in snapshot.children {
let title = (snapshot.value as? NSDictionary)?["title"] as? String
let userID = (snapshot.value as? NSDictionary)?["userID"] as? String
let mediaID = (snapshot.value as? NSDictionary)?["mediaID"] as? String
let timestamp = (snapshot.value as? NSDictionary)?["timestamp"] as? Double
and if I do print (child), this is what I get:
// print(child)
Snap (XsUwNDQB3qPdjYFCOLzANmsjjpf1-1474144681) {
mediaID = "XsUwNDQB3qPdjYFCOLzANmsjjpf1-1474144681";
timestamp = 1474144681490;
title = "outside sep 17";
userID = XsUwNDQB3qPdjYFCOLzANmsjjpf1;
}
edit: solved it. this works:
let snapDic = snapshot.value as? NSDictionary
for child in snapDic! {
print (child)
let childDic = child.value as? NSDictionary
let title = childDic?["title"] as? String
let userID = childDic?["userID"] as? String
let mediaID = childDic?["mediaID"] as? String
let timestamp = childDic?["timestamp"] as? Double

Resources