How to access values in UIViewController class from TableCell class in Swift? - ios

So, I have a UIViewController(PledgeViewController) with a TableView. When the user clicks on a UIButton(plusBtn) in the UITableViewCell(PledgeTableViewCell) of the TableView, I want to perform a write to my firebase database. But to get the exact path, I need a String(getID) from the PledgeViewController class which is received with a segue from the previous ViewController. With the MVC format that I'm using, how do I access values in the PledgeViewController to write to the database from the PledgeTableViewCell?
My PledgeViewController.swift:
import UIKit
import Foundation
import FirebaseDatabase
import Firebase
class PledgeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
var getID: String!
#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
}
let RewardRef = Database.database().reference().child("Rewards")
var rewards = [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
return cell
}
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)
}
}
My PledgeTableViewCell.swift:
import UIKit
import Firebase
import FirebaseDatabase
class PledgeTableViewCell: UITableViewCell {
#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 artcallid: Int!
#IBAction func minusBtn(_ sender: Any) {
}
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) {
}
}
Rewards.swift:
import Foundation
import Firebase
import FirebaseDatabase
class Rewards {
let ref: DatabaseReference!
// let countRef: DatabaseReference!
var rewardAmt: Int!
var rewardsLeft: Int!
var reward_class_name: String = ""
var reward_amt: String = ""
var reward_desc: String = ""
var rewardID: String = ""
var tickUpCount = 0
var tickDownCount = 0
init(text: String) {
ref = Database.database().reference().child("Fund").childByAutoId()
// countRef = Database.database().reference().child("Testing").childByAutoId()
}
init(snapshot: DataSnapshot)
{
ref = snapshot.ref
if let value = snapshot.value as? [String : Any] {
rewardAmt = value["reward_ticket_amount"] as! Int
reward_class_name = value["reward_ticket_amount_class_name"] as! String
reward_amt = value["reward_ticket_amount_txt"] as! String
reward_desc = value["reward_ticket_class_desc"] as! String
rewardsLeft = value["rewards_left"] as! Int
rewardID = snapshot.key
}
}
}
extension Rewards{
func countUp(){
tickUpCount += 1
ref.child("uppingTicket").setValue(tickUpCount)
}
}

You can try with closure
class PledgeTableViewCell: UITableViewCell {
//Define a closure
var closure:(() -> Void)? = nil
#IBAction func plusBtn(_ sender: AnyObject) {
// Do you stuff
closure?()
}
}
class PledgeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
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.closure = {
// You will get the callback in this block
// You can define the parameterized closure to return the value
}
return cell
}

You can try to add a new var
class PledgeTableViewCell: UITableViewCell {
var currentID = ""
}
and set it in cellForRowAt
cell.currentID = getID

Related

Passing Firebase Data from one view controller to detail view controller

I am looking to load data from my Firebase Database into a tableview in my main view controller and then pass that data to be more descriptive to a second view controller as my detail view controller. I am getting stuck because when i do click on the cell it will not segue to my other view controller and I am not sure how to get the data to pass. I want just the name on the first view controller and then the other data to populate on the detail view controller.
My Main View Controller--
import UIKit
import Foundation
import Firebase
import FirebaseDatabase
class ViewController: UIViewController {
var table = [FacStaffInfo]()
var ref: DatabaseReference!
#IBOutlet weak var Tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
ref = Database.database().reference().child("users")
ref.observe(DataEventType.value, with: {(snapshot) in
if snapshot.childrenCount > 0 {
self.table.removeAll()
for user in snapshot.children.allObjects as! [DataSnapshot] {
let object = user.value as? [String: AnyObject]
let title = object?["title"]
let name = object?["name"]
let email = object?["email"]
let phone = object?["phone"]
let office = object?["office"]
let bio = object?["bio"]
let user = FacStaffInfo(title: title as! String, name: name as! String, email: email as! String, phone: phone as! Int, office: office as! String, bio: bio as! String)
self.table.append(user)
self.Tableview.reloadData()
}
}
})
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return table.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "userCell") as! TableViewCell
let user: FacStaffInfo
user = table[indexPath.row]
cell.titleLabel?.text = user.title
cell.nameLabel?.text = user.name
cell.emailLabel?.text = user.email
cell.phoneLabel?.text = String(user.phone)
cell.officeLabel?.text = user.office
cell.bioLabel?.text = user.bio
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetail", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = Tableview.indexPathForSelectedRow {
let destinationController = segue.destination as! InfoViewController
destinationController.FacStaffData = [table[indexPath.row]]
}
}
}
}
My Detail View controller--
import UIKit
import Firebase
import FirebaseDatabase
class InfoViewController: UIViewController {
var FacStaffData = [FacStaffInfo]()
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
#IBOutlet weak var phoneLabel: UILabel!
#IBOutlet weak var officeLabel: UILabel!
#IBOutlet weak var bioLabel: UILabel!
//var title = ""
var name = ""
var email = ""
var phone = ""
var office = ""
var bio = ""
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = title
nameLabel.text = name
emailLabel.text = email
phoneLabel.text = phone
officeLabel.text = office
bioLabel.text = bio
print(titleLabel)
}
}
My info class--
import Foundation
import Firebase
import FirebaseDatabase
class FacStaffInfo {
var title: String
var name: String
var email: String
var phone: Int
var office: String
var bio: String
init(title: String, name: String, email: String, phone: Int, office: String, bio: String) {
self.title = title;
self.name = name;
self.email = email;
self.phone = phone;
self.office = office;
self.bio = bio
}
}
and my tableview cell--
import UIKit
import Firebase
import FirebaseDatabase
class TableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
#IBOutlet weak var phoneLabel: UILabel!
#IBOutlet weak var officeLabel: UILabel!
#IBOutlet weak var bioLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
It looks like didSelectRowAt just implements didSelectRowAt again without calling anything.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetail", sender: self)
}
}
try again with:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetail", sender: self)
}
Updated for followup:
The InfoViewController is using the default values. When you prepare the segue, you put the information into FacStaffData. This should do the trick.
class InfoViewController: UIViewController {
var FacStaffData = [FacStaffInfo]()
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
#IBOutlet weak var phoneLabel: UILabel!
#IBOutlet weak var officeLabel: UILabel!
#IBOutlet weak var bioLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = FacStaffData.title
nameLabel.text = FacStaffData.name
emailLabel.text = FacStaffData.email
phoneLabel.text = FacStaffData.phone
officeLabel.text = FacStaffData.office
bioLabel.text = FacStaffData.bio
print(titleLabel)
}
}

Swift 5- Firebase- Putting users into sections with data loaded from firebase

I have a tableview that has a list of users in a directory that are loaded in from a firebase directory. My question is how can i put them into sections similarly to that of the contact app in the iPhone. I want each user to be displayed by their name under the appropriate sections.
here is the code I have:
my main view controller:
import UIKit
import Foundation
import Firebase
import FirebaseDatabase
class ViewController: UIViewController {
//MARK: - variables for the textfield search
#IBOutlet var field: UITextField!
var filteredTable = [String]()
//MARK: - Variables for the tableview data from Firebase
var table = [FacStaffInfo]()
var ref: DatabaseReference!
#IBOutlet weak var Tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//MARK: - setting the delegate for the test field for filter
field.delegate = self
//MARK: - This is all the functionality for the loading from Firebase to the TableView
ref = Database.database().reference().child("users")
ref.observe(DataEventType.value, with: {(snapshot) in
if snapshot.childrenCount > 0 {
self.table.removeAll()
for user in snapshot.children.allObjects as! [DataSnapshot] {
let object = user.value as? [String: AnyObject]
let title = object?["title"]
let name = object?["name"]
let email = object?["email"]
let phone = object?["phone"]
let office = object?["office"]
let bio = object?["bio"]
let user = FacStaffInfo(title: title as! String, name: name as! String, email: email as! String, phone: phone as! Int, office: office as! String, bio: bio as! String)
self.table.append(user)
self.Tableview.reloadData()
}
}
})
}
}
//MARK: - add the tableview functions
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//MARK: - adding functionality for textfield search
if !filteredTable.isEmpty {
return table.count
}
//MARK: - just returning the array from the database, keep if remove textfield crap
return table.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "userCell") as! TableViewCell
let user: FacStaffInfo
user = table[indexPath.row]
cell.titleLabel?.text = user.title
cell.nameLabel?.text = user.name
cell.emailLabel?.text = user.email
cell.phoneLabel?.text = String(user.phone)
cell.officeLabel?.text = user.office
cell.bioLabel?.text = user.bio
//MARK: - testing using arrays to filter tableview data
// if !filteredTable.isEmpty {
// cell.textLabel?.text = filteredTable[indexPath.row]
// }
// else {
// cell.textLabel?.text = table.
// }
//
//
//
//
//
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetail", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = Tableview.indexPathForSelectedRow {
let destinationController = segue.destination as! InfoViewController
destinationController.FacStaffData = table[indexPath.row]
}
}
}
}
This is my data model
import Foundation
import Firebase
import FirebaseDatabase
class FacStaffInfo {
var title: String
var name: String
var email: String
var phone: Int
var office: String
var bio: String
init(title: String, name: String, email: String, phone: Int, office: String, bio: String) {
self.title = title;
self.name = name;
self.email = email;
self.phone = phone;
self.office = office;
self.bio = bio
}
}
This is my table view cell
import UIKit
import Firebase
import FirebaseDatabase
class TableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
#IBOutlet weak var phoneLabel: UILabel!
#IBOutlet weak var officeLabel: UILabel!
#IBOutlet weak var bioLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Swift 5
Declare your class as follows:
class ViewController: UIViewController
{
// MARK: Outlets
#IBOutlet weak var Tableview: UITableView!
#IBOutlet weak var field: UITextField!
// MARK: Properties
var sectionNames: [String] = []
var users: [String: [FacStaffInfo]] = [:]
var ref: DatabaseReference!
// MARK: View Controller Life Cycle
override func viewDidLoad()
{
super.viewDidLoad()
getUsersFromFirebaseDB()
}
deinit
{
ref.removeAllObservers()
}
// MARK: Private Methods
private func usersFetched(_ usersData: [FacStaffInfo])
{
for user in usersData
{
guard let userNameFirstChar = user.name.first?.uppercased() else { continue }
if var usersForKey = users["\(userNameFirstChar)"]
{
usersForKey.append(user)
users["\(userNameFirstChar)"] = usersForKey
}
else
{
// no users are stored in dictionary for key userNameFirstChar
users["\(userNameFirstChar)"] = [user]
}
}
// sort dictionary keys and set it in sectionNames
sectionNames = users.map { $0.key }.sorted()
}
private func getUsersFromFirebaseDB()
{
ref = Database.database().reference().child("users")
ref.observe(DataEventType.value, with: { [weak self] (snapshot) in
guard snapshot.childrenCount > 0 else { return }
var users: [FacStaffInfo] = []
for user in snapshot.children.allObjects as! [DataSnapshot]
{
let object = user.value as? [String: AnyObject]
let title = object?["title"]
let name = object?["name"]
let email = object?["email"]
let phone = object?["phone"]
let office = object?["office"]
let bio = object?["bio"]
let user = FacStaffInfo(title: title as! String, name: name as! String, email: email as! String, phone: phone as! Int, office: office as! String, bio: bio as! String)
users.append(user)
}
self?.usersFetched(users)
self?.Tableview.reloadData()
})
}
// MARK: Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "showDetail"
{
if let indexPath = Tableview.indexPathForSelectedRow
{
let destinationController = segue.destination as! InfoViewController
let char = sectionNames[indexPath.section]
let user = users[char]![indexPath.row]
destinationController.FacStaffData = user
}
}
}
}
Also, add the following extension:
extension ViewController: UITableViewDataSource, UITableViewDelegate
{
func numberOfSections(in tableView: UITableView) -> Int
{
sectionNames.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
{
sectionNames[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
let char = sectionNames[section]
return users[char]!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "userCell") as! TableViewCell
let char = sectionNames[indexPath.section]
let user = users[char]![indexPath.row]
cell.nameLabel?.text = user.name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
performSegue(withIdentifier: "showDetail", sender: self)
tableView.deselectRow(at: indexPath, animated: true)
}
}
Output

How to pass the value of a label in my TableCell to the TableViewController on the click of a button in the TableCell? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
So, I have a ViewController(PledgeViewController) with a UITableView and another file called PledgeTableViewCell.swift which is a UITableCell file. When someone clicks a button(plsBtn) in the PledgeTableViewCell.swift, I have set up a closure which feeds back into the PledgeViewController and I handle my operations from there. What I want to do now is this:
When someone clicks the plsBtn in the PledgeTableViewCell, I'm handling that action in the PledgeViewController. But I want to read the value of a label in the TableViewCell at that indexPath and send it to the PledgeViewController for further calculations. Can I do this with the closure itself or is there another method? Thanks!
PledgeTableViewCell.swift:
import UIKit
import Firebase
import FirebaseDatabase
class PledgeTableViewCell: UITableViewCell {
var plusBtnAction: ((Any) -> Void)?
var minusBtnAction: ((Any) -> 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
let userID = Auth.auth().currentUser!.uid
#IBAction func minusBtn(_ sender: Any) {
if var tickCount = Int(ticketCountLabel.text!) {
if(tickCount > 0)
{
tickCount -= 1
ticketCountLabel.text = String(tickCount)
}
}
self.minusBtnAction?(sender)
}
#IBAction func plusBtn(_ sender: AnyObject) {
if var tickCount = Int(ticketCountLabel.text!) {
//I WANT TO SEND THIS 'TICKCOUNT' TO THE PLEDGEVIEWCONTROLLER
tickCount += 1
ticketCountLabel.text = String(tickCount)
}
self.plusBtnAction?(sender)
}
}
PledgeViewController.swift:
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!
#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
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
/* myIndex = indexPath.row
finalId = idTable[myIndex]
let story = stories[indexPath.row]
ArtcallID = story.id
performSegue(withIdentifier: "singleArtcall", sender: self)
*/
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
rewardID = reward.rewardID
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)
}
else{
self.ticket_count = snapshot.value as! Int
self.ticket_count += 1
self.ref.setValue(self.ticket_count)
}
}) { (error) in
print(error.localizedDescription)
}
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
self.pledgeAmtLabel.text = String(reward_amt)
}) { (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)
}
}
}) { (error) in
print(error.localizedDescription)
}
}
return cell
}
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)
}
}
You can pass the label value in the closure itself along with sender.
class PledgeTableViewCell: UITableViewCell {
var plusBtnAction: ((String) -> Void)?
var minusBtnAction: ((String) -> Void)?
#IBAction func minusBtn(_ sender: Any) {
if var tickCount = Int(ticketCountLabel.text!) {
if(tickCount > 0)
{
tickCount -= 1
ticketCountLabel.text = String(tickCount)
}
self.minusBtnAction?(tickCount)
}
}
#IBAction func plusBtn(_ sender: AnyObject) {
if var tickCount = Int(ticketCountLabel.text!) {
//I WANT TO SEND THIS 'TICKCOUNT' TO THE PLEDGEVIEWCONTROLLER
tickCount += 1
ticketCountLabel.text = String(tickCount)
self.plusBtnAction?(ticketCount)
}
}
}
in cellForRow: method in PledgeViewController
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TakePledgeCell", for: indexPath) as! PledgeTableViewCell
.....
cell.plusBtnAction = { labelText in
//handle labelText here
}
}

Update initialized Data in array with variable then pass array to next view controller

I'm having issues moving the data from the selected cells from the (service2viewcontroller) to the (confirmorderviewcontroller). I am trying to move the cell data (cells with a stepper.value above 0(var quantity > 0.0 (in Service2ViewController))), I was told to pass the array to the next view controller, to do so for a stepper value above 0 I would need to also send the indexpath.row for the rows with a quantity variable above 0 correct? I don't know how to do this if anyone can help I would greatly appreciate it. also the label is not updating when I use the stepper it stays at 0, can I place the quantity variable inside of the array? the total price label in the view controller continues to function and the data is sent to the (confirmorderviewcontroller) with no issues.
first TableView (data is input and forwarded)
class Service2ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var service2Total: UILabel!
#IBOutlet weak var service2TableView: UITableView!
// service data
var Wash: [Service2] = []
//stepper and price calculation
var quantity = Double()
var totalPrice : Double = 0.0
var priceList = [Int : Double]()
var totalProductPrice = [Int : Double]()
var label : Int!
override func viewDidLoad() {
super.viewDidLoad()
Wash = Options2()
if Int(quantity) > 0{
service2TableView.reloadData()
}
priceList[0] = 3.51//price list
priceList[1] = 5.51
service2Total.text = "$0.00"
}
// create data array
func Options2() -> [Service2]{
var washOptions: [Service2] = []
let option1 = Service2(titled: "Test", pricing: "$3.51", image: #imageLiteral(resourceName: "Wash&Fold"), description:"Testing the description box", quantity: Int(quantity))
let option2 = Service2(titled: "Test", pricing: "$5.51", image: #imageLiteral(resourceName: "Wash&Fold"), description: "Testing the description box", quantity: Int(quantity))
washOptions.append(option1)
washOptions.append(option2)
return washOptions
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Wash.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let Wash1 = Wash[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "Service2Cell", for: indexPath) as! Service2TableViewCell
cell.setService(Wash: Wash1)
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 133
}
#IBAction func stepperAcn(_ sender: UIStepper) {
//change label value with stepper
let cellPosition = sender.convert(CGPoint.zero, to: service2TableView)
let indPath : IndexPath = service2TableView.indexPathForRow(at: cellPosition)!
quantity = sender.value
let getCurrentProductPrice : Double = priceList[indPath.row]! * sender.value
totalPrice = gettingPriceLabel(indPath: indPath, getCurrentProductPrice: getCurrentProductPrice)
if totalPrice == 0{
service2Total.text = ("$0.00")
}
else{
service2Total.text = ("$")+String(totalPrice)
}
print("total price",totalPrice)
print("quantity double",quantity)
service2TableView.reloadData()
}
func gettingPriceLabel(indPath: IndexPath, getCurrentProductPrice : Double) -> Double
{
totalProductPrice[indPath.row] = getCurrentProductPrice
var totalCost : Double = 0.0
let valuesArr = Array(totalProductPrice.values)
for i in 0..<valuesArr.count
{
totalCost = totalCost + valuesArr[i]
}
return totalCost
}
// add function to collect (didSelectRowAt) and send selected data to cart and prepare for segue
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
// change sender to
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let DestViewController: ConfirmorderViewController = segue.destination as! ConfirmorderViewController
if totalPrice > 0.00{
DestViewController.amount = totalPrice
}
}
}
service initializer
class Service2
{
var service2Title: String
var service2Image: UIImage
var Service2Pricing: String
var service2Description: String
var service2Quantity: Int
init(titled: String, pricing: String, image: UIImage, description: String, quantity: Int){
self.service2Title = titled
self.Service2Pricing = pricing
self.service2Image = image
self.service2Description = description
self.service2Quantity = quantity
}
}
Service 2 TableViewCell
class Service2TableViewCell: UITableViewCell {
#IBOutlet weak var service2Title: UILabel!
#IBOutlet weak var service2Stepper: UIStepper!
#IBOutlet weak var service2StepperLbl: UILabel!
#IBOutlet weak var service2Pricing: UILabel!
#IBOutlet weak var service2Image: UIImageView!
#IBOutlet weak var service2Description: UILabel!
func setService(Wash: Service2){
service2Image.image = Wash.service2Image
service2Pricing.text = Wash.Service2Pricing.description
service2Title.text = Wash.service2Title
service2Description.text = Wash.service2Description
service2StepperLbl.text = Wash.service2Quantity.description
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Second TableView (receives data)
class ConfirmorderViewController: UIViewController{
#IBOutlet weak var Total: UILabel!
#IBOutlet weak var confirmOrderTableView: UITableView!
var titled = [String]()
var amount: String = ""
//var quantity = String()
var image1 = [UIImage]()
var Price = [Double]()
override func viewDidLoad() {
super.viewDidLoad()
Total.text = amount
confirmOrderTableView.reloadData()
}
}
extension ConfirmorderViewController: UITableViewDataSource, UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titled.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ConfirmOrderTableViewCell") as! ConfirmOrderTableViewCell
cell.coTitle?.text = titled[indexPath.row]
cell.coImg?.image = image1[indexPath.row]
//cell.coQuantity.text = quantity
cell.coPrice?.text = Price.description
return cell
}
}
I have tried here. I got list of row numbers having more than 0 order. I have it stored in whichRowToBeAdd. If user decreased to Zero, respective rows will removed from this array.
With the help of Singleton Class, we can store whatever we need to show in NextViewController
var whichRowToBeAdd = [Int]() // GLOBAL
#IBAction func stepperAcn(_ sender: UIStepper) {
//change label value with stepper
let cellPosition = sender.convert(CGPoint.zero, to: service2TableView)
let indPath : IndexPath = service2TableView.indexPathForRow(at: cellPosition)!
if Int(sender.value) == 0
{
if whichRowToBeAdd.contains(indPath.row)
{
whichRowToBeAdd.remove(at: whichRowToBeAdd.index(of: indPath.row)!)
}
else
{
}
}
else
{
if whichRowToBeAdd.contains(indPath.row)
{
}
else
{
whichRowToBeAdd.append(indPath.row)
}
}
//....
//..... Your Code in your answer
}
// After stepper Action, final click of Button, which moves to Next ViewController
#IBAction func goToConfirmOrder(_ sender: UIBarButtonItem) {
print("\n\n Val_ ", whichRowToBeAdd)
singleTon.sharedInstance.orderDict.removeAll()
for i in 0..<whichRowToBeAdd.count
{
let indPath = IndexPath(row: whichRowToBeAdd[i], section: 0)
let newCell = tblVw.cellForRow(at: indPath) as! Service2TableViewCell
print("qweqwe ",newCell.testLbl.text)
let name : String = newCell.service2Title.text!
let image : UIImage = newCell.service2Image.image
let quantity : Int = Int(newCell.service2StepperLbl.text!)!
getOrderOneByOne(productName: name, productImage: image, productQuantity: quantity)
if i == (whichRowToBeAdd.count - 1)
{
self.performSegue(withIdentifier: "confirmOrderVC", sender: nil)
}
}
}
func getOrderOneByOne(productName: String, productImage : UIImage, productQuantity: Int)
{
let createDict = ["productName" : productName, "productImage" : productImage, "productQuantity" : productQuantity] as [String : Any]
singleTon.sharedInstance.orderDict.append(createDict)
}
Singleton Class
class singleTon: NSObject {
static let sharedInstance = singleTon() // Singleton Instance
var orderDict = [[String : Any]]() // Dictionary Declaration
}
Next ViewController
class ConfirmOrderViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("\n\norderDict.coun ", singleTon.sharedInstance.orderDict)
}
}
With this, you can display datas in TableView in this ConfirmOrderViewController.

Swift - tableviewcell returns empty using custom cell

I am new to swift programming and would need some help to check what is wrong in my tableviewcell. I have tried alot of great suggestions on stackoverflow.( make sure your outlets are connected, set delegate and datasource of your tableview to self)
This is my ViewController:
import UIKit
class CharacterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , APIControllerProtocol {
#IBOutlet weak var CharacterInfoView: UITableView!
var apiController:APIController!
var dataArray: [[String:Any]]?
var processcharacter= [CharacterListModel]()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor=UIColor.white
self.CharacterInfoView.estimatedRowHeight = 44
self.CharacterInfoView.rowHeight = UITableViewAutomaticDimension
self.CharacterInfoView.dataSource = self
self.CharacterInfoView.delegate = self
apiController = APIController()
apiController.delegate=self
self.navigationItem.title = "Character"
self.view.showLoading()
apiController.getCharacterData{ (statusCode, data, response, error) -> () in
self.view.stopLoading()
if(statusCode == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if !(error == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if statusCode == 200
{
do
{
self.processcharacter= CharacterListData.processData(data: data)
self.CharacterInfoView.reloadData()
}
catch(_ as NSError)
{
}
}
else
{
return
}
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.dataArray == nil
{
return 0
}
else
{
return processcharacter.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"Cell", for:indexPath) as! CharacterTableViewCell
var processcharacters= processcharacter[indexPath.row]
cell.location.text = processcharacters.location
cell.name.text = processcharacters.name
cell.characterID.text = processcharacters.characterID
cell.time.text = processcharacters.lastlocatedtime
if wecares.sos == true {
processcharacters.imagebutton = UIImage(named: "sos_icon")!
}
else{
processcharacters.imagebutton = UIImage(named: "null_button")!
}
cell.button.image = processcharacters.imagebutton
return cell
}
func reachabilityChanged(_ status: Bool) {
}
}
This is my subclass for my ViewController:
import Foundation
class CharacterListDataHelper: NSObject {
static func processData(data: AnyObject?) -> [CharacterListModel]
{
var modelList:[CharacterListModel] = [CharacterListModel]()
let darr = try? JSONSerialization.jsonObject(with: data! as! Data, options: .mutableLeaves) as! [[String:Any]]
var dataModel:CharacterListModel
for obj in darr!
{
dataModel = CharacterListModel()
dataModel.location = obj["playerLocation"] as! String
dataModel.name = obj["playerName"] as! String
dataModel.characterID= obj["playerID"] as! String
dataModel.lastlocatedtime = obj["lastUpdatedTime"] as! String
}
modelList.append(dataModel)
}
return modelList
}
}
This is my Model:
import Foundation
struct CharacterListModel {
var name: String?
var characterID: String?
var location: String?
var lastlocatedtime: String?
var imagebutton: UIImage?
var sos: Bool?
}
This is my TableViewCell:
class CharacterTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var characterID: UILabel!
#IBOutlet weak var location: UILabel!
#IBOutlet weak var lastlocatedtime: UILabel!
#IBOutlet weak var button: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
Thanks in advance!
Don't fetch data in viewDidLoad() method. Fetch in viewWillAppear and reload after getting data.

Resources