How to get index path for key - SWIFT? - ios

I'm new in Swift, so I have tableview and I need to get index path for key from firebase.
When row is clicked, I want to open a new controller where is displaying all data for that User (written in Firebase).
Here is my code for didSelectRowAt:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedGuest = guestsList[indexPath.row]
let controller = self.storyboard?.instantiateViewController(identifier: "GuestDetail") as! GuestDetailsViewController
refGuests = Database.database().reference().child("userInfo").child(uid!).child("guests")
refGuests.observeSingleEvent(of: .value) { (snapshot) in
for snap in snapshot.children.allObjects as![DataSnapshot] {
let uid = snap.key
let guestD = snap.value as! [String:AnyObject]
let guestN = guestD["guestPhoneNumber"] as! String
print("key = \(uid) and tam = \(guestN)")
}
}
controller.guestUser = selectedGuest
self.present(controller, animated: true, completion: nil)
}

I don't know how selectedUser is related to the fetched data but basically the order of the code is wrong.
As observeSingleEvent works asynchronously you have to instantiate and present the controller inside the completion closure. I suppose you have to check in the loop if selectedUser matches one of the records
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedGuest = guestsList[indexPath.row]
refGuests = Database.database().reference().child("userInfo").child(uid!).child("guests")
refGuests.observeSingleEvent(of: .value) { (snapshot) in
for snap in snapshot.children.allObjects as![DataSnapshot] {
let uid = snap.key
let guestD = snap.value as! [String:AnyObject]
let guestN = guestD["guestPhoneNumber"] as! String
print("key = \(uid) and tam = \(guestN)")
}
let controller = self.storyboard?.instantiateViewController(identifier: "GuestDetail") as! GuestDetailsViewController
controller.guestUser = selectedGuest
self.present(controller, animated: true, completion: nil)
}
}

Related

Allowing specefic users to delete post Swift 4 Firebase

i have just created so the users can comment on other users post and delete the comments if they want to delete them.
but with this code everyone can delete everyone´s comments
func getKeysValue() {
// let uid = Auth.auth().currentUser?.uid
Database.database().reference().child("posts").child(postsKey).child("comments").observe( .value) { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let commentKey = snap.key
self.keyArray.insert(commentKey, at: 0)
// print(self.keyArray)
// print("Here is the specific Key\(self.commentKey)")
}
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
getKeysValue()
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when, execute: {
Database.database().reference().child("posts").child(postsKey).child("comments").child(self.keyArray[indexPath.row]).removeValue()
self.commentsTableView.reloadData()
})
}
}
then i tryed this code to only let the user to only delete its own comments:
func getKeysValue() {
// let uid = Auth.auth().currentUser?.uid
Database.database().reference().child("posts").child(postsKey).child("comments").observe( .value) { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let commentKey = snap.key
self.keyArray.insert(commentKey, at: 0)
// print(self.keyArray)
// print("Here is the specific Key\(self.commentKey)")
}
}
}
var uid = Auth.auth().currentUser?.uid
var userID = String()
var idUser = String()
var userUID = String()
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
getKeysValue()
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when, execute: {
self.userID = self.keyArray[indexPath.row]
self.idUser = self.userID
print(" Here is the indexPath key: \(self.idUser)")
Database.database().reference().child("posts").child(postsKey).child("comments").child(self.idUser).observeSingleEvent(of: .value, with: { (snapshot) in
if let postsDictionary = snapshot.value as? [String: AnyObject] {
self.uidArray.insert(postsDictionary as NSDictionary, at: 0)
let usersArray = self.uidArray[indexPath.row] as! [String: AnyObject]
let usersKey = usersArray["uid"] as? String
self.userUID = usersKey!
print("Here is the Comment:\(self.uidArray)")
print("And here is the UID::: \(self.userUID)")
if self.uid != self.userUID {
let logInAlert = UIAlertController(title: "Failed to delete", message: "You can only delete your own comment(s)", preferredStyle: .actionSheet)
logInAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(logInAlert, animated: true, completion: nil)
}else {
let commentSuccess = self.storyboard?.instantiateViewController(withIdentifier: "CommentReloadVC")
self.present(commentSuccess!, animated: false, completion: nil)
Database.database().reference().child("posts").child(postsKey).child("comments").child(self.keyArray[indexPath.row]).removeValue()
self.commentsTableView.reloadData()
}
}
})
})
}
}
soo whats wrong with this code? the thing is that this work perfect but only on the first row off the tableview that will say that this authorazation code only works with the first comment of the post and if you try to delete any other comment below the first one then i get an error that the index is out of range on this line
let usersArray = self.uidArray[indexPath.row] as! [String: AnyObject]
and this is how it looks in the database:
this looks like it should work but it does not it's probably something really easy but i just cant figure this out so help would be much appreciated
Thanks for your time. :)

Cells for TableView are not showing

I am trying to program a social media app and I want the posts to appear in the cells. The only things in the cell are a label for the post and a label for the topic. When I run the code there are no errors but the cells are not showing in the table. I cannot seem to figure out the problem. Thank you for your guys help.
import UIKit
import Firebase
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
import SwiftKeychainWrapper
class FeedVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var postBtn: UIButton!
#IBOutlet var tableView: UITableView!
var posts = [Post]()
var post: Post!
var userName: String!
var refPosts: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
//getting a reference to the node posts
refPosts = Database.database().reference().child("posts")
//observing the data changes
refPosts.observe(DataEventType.value, with: { (snapshot) in
//if the reference have some values
if snapshot.childrenCount > 0 {
//clearing the list
self.posts.removeAll()
//iterating through all the values
for data in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let postObject = data.value as? [String: AnyObject]
let id = postObject?["id"]
let thought = postObject?["thought"]
let likes = postObject?["likes"]
//creating artist object with model and fetched values
let post = Post(_id: id as! String, _thought: thought as! String?, _likes: likes as! Int?)
//appending it to list
self.posts.append(post)
}
//reloading the tableview
self.tableView.reloadData()
}
})
/*refPosts.observe(.value, with: {(snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] { //all objects in snapshot
self.posts.removeAll()
for data in snapshot {
print(data)
if let postDict = data.value as? Dictionary<String, AnyObject>{
let key = data.key
let post = Post(postKey: key, postData: postDict)
self.posts.append(post)
}
}
}
self.tableView.reloadData()
})*/
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = posts[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell{
cell.configCell(post: post)
return cell
}else{
return PostCell()
}
}
func PostToFirebase(imgUrl: String){
let userID = Auth.auth().currentUser?.uid
Database.database().reference().child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if let data = snapshot.value as? Dictionary<String, AnyObject>{
//if let snap = snapshot.value as? [String:Any] {
let data = snapshot.value as! Dictionary<String, AnyObject>
let username = data["username"]
let post: Dictionary<String, AnyObject> = [
"username": username as AnyObject,
"likes": 0 as AnyObject
]
let firebasePost = Database.database().reference().child("posts").childByAutoId()
firebasePost.setValue(post)
self.tableView.reloadData()
}
})
}
#IBAction func postImageTapped(_ sender: AnyObject){//leads to text field box -> What are you thinking?
//present(imagePicker, animated: true, completion: nil)
//performSegue(withIdentifier: "UploadPage", sender: nil)
}
#IBAction func SignOut (_ sender: AnyObject){
try! Auth.auth().signOut()
KeychainWrapper.standard.removeObject(forKey: "uid")
dismiss(animated: true, completion: nil)
}
}
As #vadian mentioned in the comments, forcing the cast would be fine in this scenario considering you have everything setup correctly. Try adding the print statements I have below so you can see in more detail what it happening with the cells.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = posts[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell {
print("dequeueing cell")
cell.configCell(post: post)
return cell
}else{
print("initialising cell")
return PostCell()
}
}
The solution involves using the newer dequeue method that takes an index path and forcing the cast.
let post = posts[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
cell.configCell(post: post)
return cell

Can't access Firebase child

I have a firebase database reference
FIRDatabase.database().reference().child("messages").child("\(self.convoId!)").childByAutoId()
I want to access the ReceiverName from my firebase database in DisplayViewController, but when I call the database reference, I get an error because of convoId. This is how convoId was declared (in MessagesViewController).
override func viewDidLoad() {
super.viewDidLoad()
let receiverId = receiverData as! String
let receiverIdFive = String(receiverId.characters.prefix(5))
let senderIdFive = String(senderId.characters.prefix(5))
if (senderIdFive > receiverIdFive)
{
self.convoId = senderIdFive + receiverIdFive
}
else
{
self.convoId = receiverIdFive + senderIdFive
}
}
receiverData was passed from UserviewController to MessagesViewController and "senderId" is the string identifier that uniquely identifies the current user sending messages and is automatically declared in JSQMessagesViewController.h. so essentially, I can't redeclare convoId in my DisplayViewController. However, in DisplayViewController, I need to access ReceiverName.
This is how I attempted to retrieve ReceiverName:
let rootRef = FIRDatabase.database().reference()
rootRef.child("messages").observeSingleEvent(of: .value) {
(snapshot: FIRDataSnapshot) in
let loggedInUserData = snapshot
if let postsDictionary = snapshot .value as? [String: AnyObject] {
for post in postsDictionary {
self.messages.add(post.value)
}
self.MessageTableView.reloadData()
}
}
Then I populate the derived data in a tableviewcell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageTableViewCell
//Configure the cell
print(messages[indexPath.row])
let message = self.messages[indexPath.row] as! [String: AnyObject]
cell.SellerName.text = message["ReceiverName"] as? String
return cell
}
Try this inside your observeSingleEvent function:
...
for post in postsDictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
let info = value as! [String: AnyObject]
let receiver = info["ReceiverName"]!
print("\(id): \(receiver)")
self.messages.add(value)
}
}
...

Empty table view

. This function is not called so i have an empty tableview how i can fix that ? I checked it using a print and the print doesn't
appear
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : feedsviewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "feedsviewTableViewCell", for:indexPath) as! feedsviewTableViewCell
print("did call")
// Configure the cell...
let post = posts[(self.posts.count-1) - indexPath .row]["text"] as! String
// let post = FIRDatabase.database().reference().child("posts").observe(.value) { (snapshot: FIRDataSnapshot) in self.posts[(self.posts.count-1) - indexPath .row]["text"] as! String
//print((snapshot.value as! String))
cell.configure(nil, post:post,name: self.loggedinuserdata!["name"] as! String)
return cell
}
.This is the viewdidload
self.loggedinuser = FIRAuth.auth()?.currentUser
self.databaseref.child("users").child(self.loggedinuser!.uid).observeSingleEvent(of: .value) {
(snapshot:FIRDataSnapshot) in
self.loggedinuserdata = snapshot.value as? NSDictionary
self.databaseref.child("posts").child(self.loggedinuser!.uid).observeSingleEvent(of: .childAdded, with: {(snapshot: FIRDataSnapshot ) in
self.posts.append(snapshot.value as! NSDictionary)
self.feeds.insertRows(at: [IndexPath(row : 0 ,section : 0)], with: UITableViewRowAnimation.automatic)
}) {(error) in
print(error.localizedDescription)
}
}

How do I "export" values from tableview function in swift 3 [duplicate]

This question already has answers here:
Accessing a variable that is out of scope Swift
(2 answers)
Closed 5 years ago.
I have the following function:
public func tableView(_ tableView: UITableView, didSelectRowAt
indexPath: IndexPath)
{
let currentcell = telefonbog[indexPath.row]
ref = FIRDatabase.database().reference()
ref?.child("medarbejder").child(currentcell).observeSingleEvent(of:
.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let Mail = (value?["Mail"] as? String)!
let Mobil = (value?["Mobil"] as? String)!
// self.test.text = Mail
self.performSegue(withIdentifier: "kontakt", sender: self)
})
}
I see it the strings Mail and Mobil do not "export" out of this function.
My problem is that I need to use these two strings in the next window. but they are empty?
You're defining Mail and Mobil as local variables which will expire and become undefined once you leave the function (or closure in this case) - that's the normal way variables behave in Swift (or pretty much most languages).
If you want to keep the variables alive, they need to be defined outside the function as perhaps a class variable or pass them as a parameter to another function.
var mail = ""
var mobil = ""
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let currentcell = telefonbog[indexPath.row]
ref = FIRDatabase.database().reference()
ref?.child("medarbejder").child(currentcell).observeSingleEvent(of:
.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
self.mail = (value?["Mail"] as? String)!
self.mobil = (value?["Mobil"] as? String)!
self.performSegue(withIdentifier: "kontakt", sender: self)
})
}
or
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let currentcell = telefonbog[indexPath.row]
ref = FIRDatabase.database().reference()
ref?.child("medarbejder").child(currentcell).observeSingleEvent(of:
.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let mail = (value?["Mail"] as? String)!
let mobil = (value?["Mobil"] as? String)!
self.doSegue(theMail: mail, theMobile: mobile)
})
}
func doSegue (theMail: String, theMobile: String) {
//do something with mail and mobile var
self.performSegue(withIdentifier: "kontakt", sender: self)
{
That was also my first guess. but the code below dosent, a breakpoint inside the func shows me that the Var is set correct, but a breakpoint just after exiting the the func shows it go right back to ""
var Mail = ""
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let currentcell = telefonbog[indexPath.row]
ref = FIRDatabase.database().reference()
ref?.child("medarbejder").child(currentcell).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
self.Mail = (value?["Mail"] as? String)!
// let Mobil = (value?["Mobil"] as? String)!
self.performSegue(withIdentifier: "kontakt", sender: self)
})
}

Resources