Allowing specefic users to delete post Swift 4 Firebase - ios

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. :)

Related

How to get index path for key - SWIFT?

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)
}
}

How to export csv with coredata entries?

I have an app that takes in user input that is stored in core data. To simplify things, I combined 5 strings from the user inputs, separated them with a comma and then this long string is stored in core data as 1 entity. The comma is separating the individual 'strings' is what makes it a CSV.
The tableview does what it's supposed to do, but the problem lies when I try to export the coredata entries as a csv. I realise that I am not making use of the fetchedStatsArray as I should and thus it is empty. I tried appending the array with NSManagedObject but none of that work. Is there a way to fix this, such that my fetchedStatsArray is filled? If not, is there another way to make sure that when the csv is generated, it will contain all the data from coredata?
Here is most of my code:
import UIKit
import CoreData
import MessageUI
class HistoryController: UITableViewController, NSFetchedResultsControllerDelegate {
let cellId = "cellId"
var fetchedStatsArray: [NSManagedObject] = []
fileprivate lazy var fetchedResultsController: NSFetchedResultsController<AlarmItem> = {
//create fetch request
let fetchRequest: NSFetchRequest<AlarmItem> = AlarmItem.fetchRequest()
//configure fetch request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "alarmAttributes", ascending: true)]
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
fetchedResultsController.delegate = self
return fetchedResultsController
}()
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch(type) {
case .insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break;
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
break;
case .update:
//this is mostlikely where the problem lies
//self.tableView.reloadData()
if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .fade)
}
break;
#unknown default:
print("Something odd is happening")
}
}
override func viewDidLoad() {
super.viewDidLoad()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
do {
try fetchedResultsController.performFetch()
} catch let err as NSError {
print("Failed to fetch items", err)
}
}
#objc func addAlarmItem(_ sender: AnyObject) {
let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
//combined string of attributes
let myStrings: [String] = alertController.textFields!.compactMap { $0.text }
let myText = myStrings.joined(separator: ",")
self.save(myText)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addTextField { (textField) in
textField.placeholder = "Enter Name of Engineer"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Date of Alarm in DD/MM/YYYY"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Time of Alarm in 24h (eg: 2300)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Please indicate True/False (type True or False)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Insert comments (if any), or NIL"
}
if let popoverController = alertController.popoverPresentationController {
popoverController.sourceView = self.view;
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0.0, height: 0.0)
popoverController.permittedArrowDirections = []
popoverController.barButtonItem = self.navigationItem.leftBarButtonItem
}
self.present(alertController, animated: true, completion: nil)
}
func save(_ itemName: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "AlarmItem", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(itemName, forKey: "alarmAttributes")
do {
try managedContext.save()
tableView.reloadData()
} catch let err as NSError {
print("Failed to save an item", err)
}
}
#objc func exportCSV(_ sender: AnyObject) {
exportDatabase()
}
func exportDatabase() {
let exportString = createExportString()
saveAndExport(exportString: exportString)
}
func saveAndExport(exportString: String) {
let exportFilePath = NSTemporaryDirectory() + "itemlist.csv"
let exportFileUrl = NSURL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
var fileHandle: FileHandle? = nil
do {
fileHandle = try FileHandle(forUpdating: exportFileUrl as URL)
} catch {
print("filehandle has error")
}
if fileHandle != nil {
fileHandle!.seekToEndOfFile()
let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
fileHandle!.write(csvData!)
fileHandle!.closeFile()
let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
let activityViewController : UIActivityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo
]
activityViewController.popoverPresentationController?.sourceView = self.view
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(activityViewController, animated: true, completion: nil)
}
}
func createExportString() -> String {
var alarmAttributes: String?
var export: String = NSLocalizedString("Engineer Name,Date of Alarm,Time of Alarm,True or False,Engineer Comments \n", comment: "")
for (index, AlarmItem) in fetchedStatsArray.enumerated() {
if index <= fetchedStatsArray.count - 1 {
alarmAttributes = AlarmItem.value(forKey: "alarmAttributes") as! String?
let alarmAttributeStrings = alarmAttributes
export += "\(alarmAttributeStrings ?? "0") \n"
}
}
print("the app will now print: \(export) ")
return export
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
let sectionInfo = fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = fetchedResultsController.object(at: indexPath) as NSManagedObject
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
func tableView(_ tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
//fetch
let toBeDeleted = fetchedResultsController.object(at: indexPath)
//delete
fetchedResultsController.managedObjectContext.delete(toBeDeleted)
do {
try fetchedResultsController.managedObjectContext.save()
} catch let err as NSError {
print("failed to save item", err)
}
}
func tableView(_tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AlarmItem", for: indexPath)
configureCell(cell, at: indexPath)
return cell
}
func configureCell(_ cell: UITableViewCell, at indexPath: IndexPath) {
let alarmItem = fetchedResultsController.object(at: indexPath)
//configure cell
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
}
}

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

delete Table View Cells from Firebase

I have a table View full of appended messages with the logged in user and other users of the app. When I swipe a cell, I want to be able to delete it from Firebase and also automatically from the tableView. I managed to get the cell deleted from Firebase but not from the tableView. This is how the messages are initially loaded into the tableView:
func loadData()
{
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
FIRDatabase.database().reference().child("messages").observeSingleEvent(of: .value, with: { (snapshot:FIRDataSnapshot) in
if let postsDictionary = snapshot .value as? [String: AnyObject] {
for post in postsDictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
let info = value as! [String: AnyObject]
let convoId = info["convoId"]
let toId = info["ReceiverId"] as! String!
let fromId = info["senderId"] as! String!
if (toId == self.loggedInUserUid || fromId == self.loggedInUserUid) {
let refs = FIRDatabase.database().reference().child("user-messages").child(convoId as! String).child(uid)
refs.observe(.childAdded, with: { (snapshot) in
self.messageId = snapshot.key
let ref = FIRDatabase.database().reference().child("messages").child(convoId as! String).child(self.messageId!)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let message = Message(dictionary: dictionary)
if let receiver = message.convoId {
self.messagesDictionary[receiver] = message
self.messages = Array(self.messagesDictionary.values)
print(self.messages)
self.messages.sort(by: { (message1, message2) -> Bool in
return (message1.timestamp?.int32Value)! > (message2.timestamp?.int32Value)!
})
}
//this will crash because of background thread, so lets call this on dispatch_async main thread
DispatchQueue.main.async(execute: {
self.MessageTableView.reloadData()
})
}
}, withCancel: nil) })}
}
}}})
}
Here is how I perform the delete function in Firebase and attempt to perform a delete function in the tableView:
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
let message = messages[(indexPath.row)]
self.deletemessage = message.convoId
FIRDatabase.database().reference().child("messages").observeSingleEvent(of: .value, with: { (snapshot:FIRDataSnapshot) in
if let postsDictionary = snapshot .value as? [String: AnyObject] {
for post in postsDictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
let info = value as! [String: AnyObject]
let convoId = info["convoId"]
let ref = FIRDatabase.database().reference().child("user-messages").child(self.deletemessage!).child(uid)
ref.observe(.childAdded, with: { (snapshot) in
self.messageId = snapshot.key
FIRDatabase.database().reference().child("user-messages").child(self.deletemessage!).child(uid).child( self.messageId!).removeValue(completionBlock: { (error, ref) in
if error != nil {
print("error \(error)")
}else{
}})})}}}})
self.messages.remove(at: indexPath.row)
self.MessageTableView.deleteRows(at: [indexPath], with: .automatic)
}
}
it deletes from the tableView but crashes and gives me an error on self.messages.remove(at: indexPath.row) fatal error: Index out of Range.
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let state = id[indexPath.row] //it store the child key to be removed. here id array is not displayed but used as backend process
print(state) // (Not required)
names.remove(at: indexPath.row) //Remove the selected name from array used in TableView that is displayed in cell
tableView.deleteRows(at: [indexPath], with: .fade) // TableView Animation
Database.database().reference().child("artists").child(id[indexPath.row]).removeValue() // remove the child referred using id from database
id.remove(at: indexPath.row) // removing selected if from id array locally
}
}
Try the following code In your case please and let me know issue still Exists
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
let message = messages[(indexPath.row)]
self.deletemessage = message.convoId
FIRDatabase.database().reference().child("messages").observeSingleEvent(of: .value, with: { (snapshot:FIRDataSnapshot) in
if let postsDictionary = snapshot .value as? [String: AnyObject] {
for post in postsDictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
let info = value as! [String: AnyObject]
let convoId = info["convoId"]
let ref = FIRDatabase.database().reference().child("user-messages").child(self.deletemessage!).child(uid)
ref.observe(.childAdded, with: { (snapshot) in
self.messageId = snapshot.key
FIRDatabase.database().reference().child("user-messages").child(self.deletemessage!).child(uid).child( self.messageId!).removeValue(completionBlock: { (error, ref) in
if error != nil {
print("error \(error)")
}
})
})
}
}}})
self.messages.remove(at: indexPath.row)
self.MessageTableView.deleteRows(at: [indexPath], with: .automatic)
}
}
Try this it occur because you are deleting value correct but under a handler which even caused a error in my project . data in messages is loaded from database so if value is not delete from database it will update again even if u remove from array. so please try this code

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