Adding cell to Table view when button tapped in swift - ios

i have to views in my app. mainMeasurements and historyMode. in main measurement, user can take photo and measure distance, speed and time. I need that app will save that measured datas in TableView in a historyMode, when reset button tapped (like a recents in a phone app). i already prepared datas and commented them. it should add cells to table view with image and "lastTop..." datas and show old ones too
class mainMeasurements: UIViewController, CLLocationManagerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
var speedArray: [String] = []
var arrayOfImages: [UIImage] = []
var distanceArray: [Int] = []
var lastTopDistance: String?
var lastTopSpeed: String?
var lastTopTime: String?
#IBOutlet weak var takePhoto: UIButton!
#IBOutlet weak var mountainImage: UIImageView!
#IBOutlet weak var speedLabel: UILabel!
#IBOutlet weak var distanceLabel: UILabel!
#IBOutlet weak var timerLabel: UILabel!
#IBOutlet weak var resetButtonLabel: UIButton!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "switchToHistory"{
// let historyModeVc = segue.destination as! historyMode
// historyModeVc.memoryPhoto = arrayOfImages.last
// historyModeVc.historySpeedLabelMM = lastTopSpeed
// historyModeVc.historyDistanceLabelMM = lastTopDistance
// historyModeVc.historyTimerLabelMM = lastTopTime
}
}
#IBAction func resetDidTouch(_ sender: UIButton) {
arrayOfImages.append(mountainImage.image!)
self.lastTopSpeed = self.maxSpeed
self.lastTopDistance = self.distanceLabel.text
self.lastTopTime = self.timerLabel.text
self.arrayOfImages.append(self.mountainImage.image!)
}
}
AND
import UIKit
class historyMode: UIViewController {
var memoryPhoto: UIImage?
var historyTimerLabelMM: String?
var historySpeedLabelMM: String?
var historyDistanceLabelMM: String?
override func viewDidLoad() {
super.viewDidLoad()
// historyDistanceLabel.text = historyDistanceLabelMM
// historySpeedLabel.text = historySpeedLabelMM
// historyTimerLabel.text = historyTimerLabelMM
// historyImage.image = memoryPhoto
}

If I'm not mistaken, you're inquiring about how to display your data on a table view?
You can parse your data like this and pass it to historyMode:
struct YourData {
var arrayOfImages: [UIImage]
var lastTopDistance: String?
var lastTopSpeed: String?
var lastTopTime: String?
}
Create a custom cell:
class CustomCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// configure your cell UI
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func set(with data: YourData) {
// initialize your properties with the data you provide
}
}
Register your custom cell with historyMode and pass your data to the custom cell:
var yourDataArray: [YourData]!
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
let yourData = yourDataArray[indexPath.row]
cell.set(with: yourData)
return cell
}

Add new element to your dataSource and use NotificationCentre to call tableView.reloadData() in historyMode

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

How to pass the data from view controller to the table view controller?

How to pass data from view controller to table view controller? and also how to store the selected data to the table view controller? but The output shows multiple row, how to make it based on the user click at the bag? and how to pass the data inside it?
! ]2
Here my Item Detail View Controller
import UIKit
class ItemDetailViewController: UIViewController {
var items = [item]()
var name : String = ""
var price : String = ""
var imagee : String = ""
#IBOutlet weak var labelname: UILabel!
#IBOutlet weak var image: UIImageView!
#IBOutlet weak var labelprice: UILabel!
//here the button to add to the table view
#IBAction func addtobag(_ sender: Any) {
let viewController = storyboard?.instantiateViewController(withIdentifier: "BagViewController") as? BagViewController
viewController?.name = self.name
viewController?.imagee = self.imagee
viewController?.price = self.price
viewController?.items = self.items
navigationController?.pushViewController(viewController!, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
labelname.text = name
labelprice.text = price
image.image = UIImage(named: imagee)
}
}
And here my Bag View Controller
import UIKit
class BagViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var totalprice: UILabel!
#IBOutlet weak var tableview: UITableView!
var items = [item]()
var name : String = ""
var price : String = ""
var imagee : String = ""
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
tableview.dataSource = self
// Do any additional setup after loading the view.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return name.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as! ShoppingTableViewCell
return cell
}
}
and here my Shopping Table View
import UIKit
class ShoppingTableViewCell: UITableViewCell {
#IBOutlet weak var dfs: UIImageView!
#IBOutlet weak var labelname: UILabel!
#IBOutlet weak var labelprice: UILabel!
#IBOutlet weak var stepperlabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func stepper(_ sender: UIStepper) {
stepperlabel.text = String(Int(sender.value))
}
}
I think your logic is kind of bad, you're instantiating a VC in code but you have a segue, I recommend you pass data through the prepare function:
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
if let vc = segue.destination as? BagViewController {
vc.name = self.name
vc.imagee = self.imagee
vc.price = self.price
vc.items = self.items
}
// Pass the selected object to the new view controller.
}
And in your addtobag IBAction you just will call the segue, I recommend you to use a String based segue extension String+PerformSegue.swift it lets you easily perform segue in a given ViewController like this:
#IBAction func addtobag(_ sender: Any) {
"nameOfTheSegue".performSegue(on: self)
// If you don't want to use String+PerformSegue.swift uncomment
// the next line and comment the last one.
// self.performSegue(withIdentifier: "nameOfTheSegue", sender: nil)
}

Why i only see the last element of array in a table view in swift 5?

I have a UI as given below and when i click save button in UI i want to add three values on top of the view to a table view, in which has three different labels for representing them and a custom structure to define the model. But my problem is that i can only append one element but what i want is to keep previously added elements in that array and show them in a tableView.
Here is the UI image
Here is the code:
MainViewController.swift
class MainViewController: UIViewController {
#IBOutlet weak var minDbLabel: UILabel!
#IBOutlet weak var averageDbLabel: UILabel!
#IBOutlet weak var maximumDbLabel: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "saveRecord" {
let recordVC = segue.destination as! RecordTableViewController
recordVC.record.minimumValue = (minDbLabel.text! as NSString).floatValue
recordVC.record.averageValue = (averageDbLabel.text! as NSString).floatValue
recordVC.record.maximumValue = (maximumDbLabel.text! as NSString).floatValue
recordVC.recordsArray.append(recordVC.record)
}
}
#IBAction func save(_ sender: UIButton){
self.performSegue(withIdentifier: "saveRecord", sender: nil)
}
}
RecordTableViewController.swift:
class RecordCell: UITableViewCell {
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var minimumValueLabel: UILabel!
#IBOutlet weak var averageValueLabel: UILabel!
#IBOutlet weak var maximumValueLabel: UILabel!
}
class RecordTableViewController: UITableViewController {
let cellIdentifier: String = "cellID"
var recordsArray = [Record]()
var record: Record = Record()
override var shouldAutorotate: Bool {
return false
}
override func viewDidLoad() {
super.viewDidLoad()
let swipe = UISwipeGestureRecognizer(target: self, action: #selector(swipeRight(_:)))
swipe.direction = .right
self.view.addGestureRecognizer(swipe)
tableView.insertRows(at: [IndexPath(row: recordsArray.count - 1, section: 0)], with: .automatic)
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recordsArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! RecordCell
cell.minimumValueLabel.text = "\(recordsArray[indexPath.row].minimumValue)"
cell.averageValueLabel.text = "\(recordsArray[indexPath.row].averageValue)"
cell.maximumValueLabel.text = "\(recordsArray[indexPath.row].maximumValue)"
return cell
}
}
Record.swift
struct Record {
var minimumValue: Float = .nan
var averageValue: Float = .nan
var maximumValue: Float = .nan
}
Thanks in advance.
Note: I already have searched on Google to find an answer but to no avail.
you should append the data in recordsArray in MainViewController first before performing the segue. See the code below
class MainViewController: UIViewController {
#IBOutlet weak var minDbLabel: UILabel!
#IBOutlet weak var averageDbLabel: UILabel!
#IBOutlet weak var maximumDbLabel: UILabel!
var recordsArray = [Record]()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "saveRecord" {
let recordVC = segue.destination as! RecordTableViewController
var record = Record()
record.minimumValue = Float(minDbLabel.text!) ?? 0.0
record.averageValue = Float(averageDbLabel.text!) ?? 0.0
record.maximumValue = Float(maximumDbLabel.text!) ?? 0.0
self.recordsArray.append(record)
recordVC.recordsArray = self.recordsArray
}
}
#IBAction func save(_ sender: UIButton){
self.performSegue(withIdentifier: "saveRecord", sender: nil)
}
}
Just replace your MainViewController with the code above and it should work.

Button on tableview cell is not working - swift

I have a button on my custom tableview cell that is showing the users name. When you click on it, you should be taken to his/her profile but nothing happens?
Here is my custom tableview cell class (commentsTableViewCell.swift) :
import UIKit
protocol commentsTableViewCellDelegate {
func namesIsTapped(cell: commentsTableViewCell)
}
class commentsTableViewCell: UITableViewCell {
#IBOutlet weak var nameButton: UIButton!
#IBOutlet weak var commentLabel: UILabel!
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var uidLabel: UILabel!
var delegate: commentsTableViewCellDelegate?
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
}
#IBAction func nameIsTapped(sender: AnyObject) {
//4. call delegate method
//check delegate is not nil
if let _ = delegate {
delegate?.namesIsTapped(self)
} else {
print("Delegate is \(delegate)")
}
}
}
Here is the important part of commentsTableViewController.swift:
class commentsTableViewController: UITableViewController, commentsTableViewCellDelegate, UITextViewDelegate {
#IBOutlet weak var commentLabel: UITextView!
#IBOutlet weak var theLabel: UILabel!
var dataGotten = "Nothing"
var updates = [CommentSweet]()
func namesIsTapped(cell: commentsTableViewCell) {
//Get the indexpath of cell where button was tapped
//let indexPath = self.tableView.indexPathForCell(cell)
let allDataSend = cell.nameButton.titleLabel?.text!
self.performSegueWithIdentifier("toDetailtableViewController", sender: allDataSend)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toDetailtableViewController" {
if let nextVC = segue.destinationViewController as? theProfileTableViewController {
nextVC.viaSegue = sender! as! String
}
}
}
override func viewDidLoad() {
Kindly set the delegate to self.
In cellforRowIndexPath
commentsTableViewCell.delegate = self
Where commentsTableViewCell is the custom UITableViewCell object
I suggest to handle the action of the cell's button in the viewController. You can recognize which button has been tapped by setting a tag for it.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
cell.myButton?.tag = indexPath.row
cell.myButton?.addTarget(self, action: #selector(), for: .touchUpInside)
return cell
}
func namesIsTapped(tappedButton: UIButton) {
// get the user (from users array for example) by using the tag, for example:
let currentUser = users[tappedButton.tag]
// do whatever you want with this user now...
}

Swift Emptying array when returning from tableview

In first VC I have an array with images (which I picked - array.append) which goes over prepareforsegue to another VC with tableview, and tableview reads that array and everything works, however when going back from tableview to first VC to pick another set of images (array.append) tableview is populating cells with set of previous picked images, because array have previous picked images. How could I make that tableview remember only the last added images.
ViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var image1: UIImageView!
#IBOutlet weak var image2: UIImageView!
#IBOutlet weak var image3: UIImageView!
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
var array = [UIImage]()
var array2 = [String]()
var number = 0
#IBAction func gamb(sender: UIButton) {
}
#IBAction func gamb2(sender: UIButton) {
array.append(self.image2.image!)
array2.append(self.label2.text!)
}
#IBAction func gamb3(sender: AnyObject) {
array.append(self.image1.image!)
array2.append(self.label1.text!)
}
#IBAction func gamb4(sender: UIButton) {
array.append(self.image3.image!)
array2.append(self.label3.text!)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destVC = segue.destinationViewController as! TableViewController
let priljepak = self.array
destVC.array = priljepak
let priljepak2 = self.array2
destVC.array2 = priljepak2
}
}
TableViewController
import UIKit
class TableViewController: UIViewController,UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var array = [UIImage]()
var array2 = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.imageView?.image = array[indexPath.row]
cell.textLabel!.text = array2[indexPath.row]
return cell
}
}
In the first ViewController, override viewWillAppear. Call super and empty the arrays.
override func viewWillAppear(animated:bool) {
super.viewWillAppear(animated)
array = [UIImage]()
array2 = [String]()
}
This'll cause any selection to be removed when returning to the first VC.
Insert the following override into your ViewController:
override func viewWillAppear(animated: Bool){
super.viewWillAppear(animated)
array.removeAll()
array2.removeAll()
}
This will clean the arrays in your first view controller, when TableViewController is dismissed.

Resources