1

I have a dynamic table inside a view fetching data from Firebase. I need to transfer data from the label in the TableViewCell to a label in the View. Since this is happening on the same screen, the prepareForSegue method cannot be implemented. I am currently writing the database based on the value from the label in the tableViewCell and then fetching it in the label in the View. But there is a considerable lag and sometimes the values differ as well. Is there any way to do it locally? I have to files, one for the TableViewCell and one for the View itself.

P.S I am fairly new to Swift and iOS

This is what my Screen currently looks like And I wish to send data from point A to point B

This the PledgeViewController

    import UIKit
    import Foundation
    import FirebaseDatabase
    import Firebase

    class PledgeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{


var getID: String!
var rewards = [Rewards]()
var ticket_count: Int = 0
var ref: DatabaseReference!
let userID = Auth.auth().currentUser!.uid
var rewardID: String!
var total_pledge: Int = 0

@IBOutlet weak var pledgeAmtLabel: UILabel!
@IBOutlet weak var RewardChooseTable: UITableView!
@IBAction func pledgeBtn(_ sender: Any) {
    //get the text from the label and run all the checks to see if the tickets are available
    //just sending user to the next screen for now




}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let reward = rewards[indexPath.row]
    let id = reward.rewardID
    //reward.countUp()

    print("The reward that was touched is: " + id )
    print("One of the buttons were touched")
}

let RewardRef = Database.database().reference().child("Rewards")


func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return rewards.count
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "TakePledgeCell", for: indexPath) as! PledgeTableViewCell
    let reward = rewards[indexPath.row]
    cell.reward = reward
    cell.currentID = getID

    cell.plusBtnAction = { sender in

        let reward = self.rewards[indexPath.row]
        cell.reward = reward
        let local_id = reward.rewardID

        self.ref=Database.database().reference().child("Fund_Project_Request").child(self.getID).child(self.userID).child(local_id).child("Ticket_count")


        self.ref.observeSingleEvent(of: .value, with: { (snapshot) in
            // Get user value

            if snapshot.value is NSNull{
                self.ticket_count = 0
                self.ticket_count += 1
                self.ref.setValue(self.ticket_count)

                Database.database().reference().child("Rewards").child(self.getID).child(local_id).child("reward_ticket_amount").observeSingleEvent(of: .value, with: { (snapshot) in
                    // Get user value
                    let reward_amt = snapshot.value as! Int

                    let current_value = Int(self.pledgeAmtLabel.text!)

                    print("current value in the label is:" + String(current_value!) )
                    print("new updated value is:" + String(reward_amt))
                    print("reward_amt is:", reward_amt)


                    self.pledgeAmtLabel.text = String(reward_amt + current_value!)

                    self.total_pledge = reward_amt + current_value!

                }) { (error) in
                    print(error.localizedDescription)
                }



            }


            else{
                self.ticket_count = snapshot.value as! Int
                self.ticket_count += 1
                self.ref.setValue(self.ticket_count)

                Database.database().reference().child("Rewards").child(self.getID).child(local_id).child("reward_ticket_amount").observeSingleEvent(of: .value, with: { (snapshot) in
                    // Get user value
                    let reward_amt = snapshot.value as! Int

                    let current_value = Int(self.pledgeAmtLabel.text!)

                    print("current value in the label is:" + String(current_value!) )
                    print("new updated value is:" + String(reward_amt))
                    print("reward_amt is:", reward_amt)


                    self.pledgeAmtLabel.text = String(reward_amt + current_value!)


                    self.total_pledge = reward_amt + current_value!

                }) { (error) in
                    print(error.localizedDescription)
                }

            }


        }) { (error) in
            print(error.localizedDescription)
        }


        // Do whatever you want from your button here.
    }



    cell.minusBtnAction = { sender in

        let reward = self.rewards[indexPath.row]
        cell.reward = reward
        let local_id = reward.rewardID

    self.ref=Database.database().reference().child("Fund_Project_Request").child(self.getID).child(self.userID).child(local_id).child("Ticket_count")
        self.ref.observeSingleEvent(of: .value, with: { (snapshot) in
            // Get user value

            if snapshot.value is NSNull{

            }

            else{

                self.ticket_count = snapshot.value as! Int
                if(self.ticket_count != 0)
                {
                    self.ticket_count -= 1
                    self.ref.setValue(self.ticket_count)

                    Database.database().reference().child("Rewards").child(self.getID).child(local_id).child("reward_ticket_amount").observeSingleEvent(of: .value, with: { (snapshot) in
                        // Get user value
                        let reward_amt = snapshot.value as! Int

                        let current_value = Int(self.pledgeAmtLabel.text!)

                        print("current value in the label is:" + String(current_value!) )
                        print("new updated value is:" + String(reward_amt))
                        print("reward_amt is:", reward_amt)


                        self.pledgeAmtLabel.text = String( current_value! - reward_amt)

                        self.total_pledge = current_value! - reward_amt



                    }) { (error) in
                        print(error.localizedDescription)
                    }





                }
            }


        }) { (error) in
            print(error.localizedDescription)
        }



    }



    return cell

}


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let vc = segue.destination as! SummaryViewController // else {return}
    vc.getID = getID
    vc.pledgeAmt = total_pledge
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)


    RewardRef.child(getID).observe(.value, with: { (snapshot) in
        self.rewards.removeAll()

        for child in snapshot.children {
            let childSnapshot = child as! DataSnapshot
            let reward = Rewards(snapshot: childSnapshot)
            self.rewards.insert(reward, at: 0)
        }

        self.RewardChooseTable.reloadData()
    })

}




override func viewDidLoad() {
    super.viewDidLoad()


    print("The id received from the SingleViewControl is:" + getID)
    }

    }

And this is the TableViewCell

   import UIKit
         import Firebase
         import FirebaseDatabase


    class PledgeTableViewCell: UITableViewCell {

var plusBtnAction: ((String) -> Void)?
var minusBtnAction: ((String) -> Void)?

@IBOutlet weak var rewardAmtLabel: UILabel!
@IBOutlet weak var ticketClasslabel: UILabel!
@IBOutlet weak var ticketDescLabel: UILabel!

@IBOutlet weak var ticketCountLabel: UILabel!
@IBOutlet weak var plusBtn: UIButton!
@IBOutlet weak var minusBtn: UIButton!

var ref: DatabaseReference!
var currentID = ""
var ticket_count: Int = 0

@IBAction func minusBtn(_ sender: Any) {

    if var tickCount = Int(ticketCountLabel.text!) {

        if(tickCount > 0)
        {
            tickCount -= 1
            ticketCountLabel.text = String(tickCount)
            self.minusBtnAction?(String(tickCount))
        }

    }


  //  self.minusBtnAction?(String(tickCount))
}


var reward: Rewards! {
    didSet {

        rewardAmtLabel.text = "Rs. " + String(reward.rewardAmt)
        ticketClasslabel.text = reward.reward_class_name
        ticketDescLabel.text = reward.reward_desc
        print(reward.reward_class_name + " is one of the rewards")
    }

}

@IBAction func plusBtn(_ sender: AnyObject) {


    if var tickCount = Int(ticketCountLabel.text!) {
        tickCount += 1
        ticketCountLabel.text = String(tickCount)
        print("The ticket counting before sending is:" + String(tickCount))
        self.plusBtnAction?(String(tickCount))

    }



}


    }
Dhanya Baid
  • 115
  • 1
  • 9
  • 1
    Possible duplicate of [Passing Data between View Controllers](https://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) – Tj3n Jul 24 '18 at 03:42
  • 1
    You are looking for `Passing data back to the previous View Controller` in the duplicate link, create a delegate inside your cell class, then implement callback in your viewController class – Tj3n Jul 24 '18 at 03:43
  • @Tj3n The question was based on Objective C if I am not mistaken and I am unable to do it in Swift – Dhanya Baid Jul 24 '18 at 03:44
  • The 2nd answer is Swift – Tj3n Jul 24 '18 at 03:46

1 Answers1

1

Create a delegate for your cell class:

import UIKit
import Firebase
import FirebaseDatabase

//Create delegate for tableview cell to pass information about cell interactions
  //Any parent view that needs this info can be the delegate of each cell

protocol PledgeTableViewCellDelegate: class {
  func minusTapped(id: String, ticketCount: Int)
  func plusTapped(id: String, ticketCount: Int)
}

class PledgeTableViewCell: UITableViewCell {

  //I don't believe you would need these actions anymore
  //var plusBtnAction: ((String) -> Void)?
  //var minusBtnAction: ((String) -> Void)?

  @IBOutlet weak var rewardAmtLabel: UILabel!
  @IBOutlet weak var ticketClasslabel: UILabel!
  @IBOutlet weak var ticketDescLabel: UILabel!

  @IBOutlet weak var ticketCountLabel: UILabel!
  @IBOutlet weak var plusBtn: UIButton!
  @IBOutlet weak var minusBtn: UIButton!

  var ref: DatabaseReference!
  var currentID = ""
  var ticket_count: Int = 0

  //Make this weak to avoid retain cycles
  weak var delegate: PledgeTableViewCellDelegate?

  @IBAction func minusBtn(_ sender: Any) {
    //Maybe use nil coalescing instead of force unwrapping here
    if var tickCount = Int(ticketCountLabel.text ?? "") {
      if(tickCount > 0) {
        tickCount -= 1
        ticketCountLabel.text = String(tickCount)

        //Call delegate function here
        delegate?.minusTapped(id: currentID, ticketCount: tickCount)

        //I believe this can be removed:
          //self.minusBtnAction?(String(tickCount))
      }
    }
  }


  var reward: Rewards! {
    didSet {
      rewardAmtLabel.text = "Rs. " + String(reward.rewardAmt)
      ticketClasslabel.text = reward.reward_class_name
      ticketDescLabel.text = reward.reward_desc
      print(reward.reward_class_name + " is one of the rewards")
    }
  }

  @IBAction func plusBtn(_ sender: AnyObject) {
    //Maybe use nil coalescing instead of force unwrapping here
    if var tickCount = Int(ticketCountLabel.text ?? "") {
      tickCount += 1
      ticketCountLabel.text = String(tickCount)
      print("The ticket counting before sending is:" + String(tickCount))

      //Call delegate function here:
      delegate?.plusTapped(id: currentID, ticketCount: tickCount)

      //I believe this can also be removed
        //self.plusBtnAction?(String(tickCount))
    }
  }
}

Then, in the view controller you want to do things based on this cell's interactions, make sure you conform to the protocol that was created.

So in cellForRow in your PledgeViewController you would add:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "TakePledgeCell", for: indexPath) as! PledgeTableViewCell
  let reward = rewards[indexPath.row]
  cell.reward = reward
  cell.currentID = getID

  //Make this view controller the delegate of the cell
  cell.delegate = self
}

Then you can add this to your PledgeViewController:

//Add extension to PledgeViewController for tableview cell delegate functions
extension PledgeViewController: PledgeTableViewCellDelegate {
  func minusTapped(id: String, ticketCount: Int) {
    //Do stuff based on cell interaction
  }

  func plusTapped(id: String, ticketCount: Int) {
    //Do stuff based on cell interaction
  }
}
Kayla Galway
  • 662
  • 4
  • 7
  • Hey but he's using "let local_id = reward.rewardID" inside the TableViewController which is used to get the id. How would you do the same with a delegate? – Arjun Ram Jul 25 '18 at 09:05