make UITableView updates from class of the cells populating it - ios

I have used the same nib file to populated a UITableView. There are 2 different functionalities I have built out for these cells. If you anywhere on the cell other than a small button it runs a function and segues to another page. However if you click the small button, I want to update the UITableView and input a cell below the clicked cell, as a sort of dropdown. I have the below to successfully run a separate functionality:
import UIKit
class ContactCell: UITableViewCell {
//below are the outlets for the conact cells
#IBOutlet weak var msgStatus: UIView!
#IBOutlet weak var contactName: UILabel!
#IBOutlet weak var dropDown: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
msgStatus.layer.cornerRadius = msgStatus.frame.size.width/2
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func dropDown(_ sender: Any) {
print("selected drop down")
}
}
Moving forward I need to be able to get the index of the current cell and perform a UITableView update from the UITableViewCell's class. How would I be able to do this?

You could do this with delegation. Create a delegate protocol for your ContactCell:
protocol ContactCellDelegate {
func pleaseAddDropdown(to: ContactCell)
}
Then set up a delegate parameter for the cell:
var delegate: ContactCellDelegate?
Then subscribe your table view to the ContactCellDelegate protocol (you will have to subclass if you are using a standard UITableView). This means you will need to write an implementation of pleaseAddDropdown() for your table view class. When you dequeue a cell make sure the delegate parameter is assigned to your table view.
Now in your implementation of dropdown() you just need to do something like:
guard let _ = delegate else { return }
delegate!.pleaseAddDropdown(to: self)
Which will send that message up to the table view which can take the appropriate action.
Hope that helps.

Related

How to reload table from tableView?

How to reload tableView from custom cell? Cell has two buttons inside if the button is clicked table should reload.
I was trying to add protocol inside UITableViewCell File and reload it once the button is clicked but the protocol function inside UITableViewController is not being called.
Here the code inside UITableViewCell:
protocol reloadTableDelegate {
func reloadTableonClick()
}
class TableViewCell: UITableViewCell {
var delegate : reloadTableDelegate?
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button1: UIButton!
var button1Clicked = false
var button2clicked = false
#IBAction func button1Action(_ sender: Any) {
button2clicked = true
delegate?.reloadTableonClick()
}
#IBAction func button2Action(_ sender: Any) {
delegate?.reloadTableonClick()
}
}
This is what I am doing inside UITableView to reload table:
extension TableViewController : reloadTableDelegate {
func reloadTableonClick() {
tableView.reloadData()
}
}
First you need to add an action to the button. You can do it like this:
if myButton.target(forAction: #selector(self.myButtonTapped()), withSender: nil) == nil { //Check that we don't add it multiple times
myButton.addTarget(self, action: #selector(self.myButtonTapped()), for: .touchUpInside)
}
This line has to be inside the cellForRowAtIndexPath.
Then in your view controller make a function like this:
func myButtonTapped() {
self.tableView.reloadData()
}
From the example you provided in your code you should also be setting the delegate to the cell. Meaning in cellForRowAtIndexPath you should set:
myCell.delegate = self
And in your view controller implement those methods like you're already doing.
try adding tableView.reloadData() anytime it needs to update.

How To Transfer Data from a Table View Cell to a View Controller

In my app I have a row of table view cells, each with a stepper and three labels. The stepper changes the value of a label in a table view cell. The problem I am facing is that when I try to transfer this data to the view controller the table view is on it does not transfer the data. I need each cell in the table view to give me a specific value so I have the code for the table view cell set up like this set up like this.
import UIKit
class ItemSearchCell: UITableViewCell {
#IBAction func itemAmountChanger(_ sender: UIStepper) {
itemQuantyWanted.text = "\(Int(sender.value))"
SearchResults().itemResultsAmountWanted.insert(Int(sender.value), at: position)
}
#IBOutlet weak var amountChangerValue: UIStepper!
#IBOutlet weak var areaView: UIView!
#IBOutlet weak var itemName: UILabel!
#IBOutlet weak var itemPrice: UILabel!
#IBOutlet weak var itemQuantyWanted: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
I then take this data and transfer it to a new viewcontroller when a button on the viewcontroller with the tableview is pressed. However the data is not sent by the stepper. The code used for sending the data is this.
var itemResultsName:[String]=[]
var itemResultsAmountWanted:[Int]=[]
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let nextView = segue.destination as! CategorsSearch
if segue.identifier == "Return"{
if itemResults.count != 0{
for i in 0 ... (itemResults.count-1){
nextView.returningItemsName.append(itemResultsName[i])
nextView.returningItemsAmountWanted.append(itemResultsAmountWanted[i])
}
}
}
}
My question is how do I transfer data from a table view cell to a view controller that the table view is on without the use a seugeway.
I am using the latest version of xcode 8.
I think the problem is how you modeled your project.
Let's describe the problem.
You need a list and the list is a representation from a some data source, like Array. If you have an array you can match the selectedIndex from list and get the value from array.
In the TableView you have delegates, and this delegate return how cell was selected with id, so get this id and get the data from your array.
I hope to help you to find the solution

Hiding buttons in cells

I am developing app which users will choose one of the two pictures in one cell. My prototype cell looks like :
and I have
cell.rightVoteButton.addTarget(self, action: #selector(voteRightButtonPressed), forControlEvents: .TouchUpInside)
cell.leftVoteButton.addTarget(self, action: #selector(voteLeftButtonPressed), forControlEvents: .TouchUpInside)
in the tableView function.
func voteRightButtonPressed(sender:UIButton){
print("Right Vote clicked is \(sender.tag)")
print(self.polls[sender.tag].poll_id)
}
in this way I am printing the polls id and cells index.
I want to hide the Vote button after clicking specific cell.
For example if I click the vote in first cell and the left picture, I want to hide the two buttons on the first cell. I now the cell's index but how can hide the buttons in specific cell.
My Custom TableViewCell:
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var leftImage: UIImageView!
#IBOutlet weak var rightImage: UIImageView!
#IBOutlet weak var userPicture: UIImageView!
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
#IBOutlet weak var pollDescription: 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
}
}
Rather than using tags, which have no intrinsic meaning and are easy to confuse, you can say something like:
func voteRightButtonPressed(sender:UIButton){
let location = self.tableView.convertPoint(sender.bounds.origin, fromView:sender)
let indexPath = self.tableView.indexPathForRowAtPoint(location)
if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? CustomUITableViewCell {
//hide views in cell and update your model to reflect vote.
}
print("Right Vote clicked is \(indexPath.row)")
print(self.polls[indexPath.row].poll_id)
}
Once you have the cell you can hide the views you want and you can update your model to reflect the vote just cast.
I suppose you have a tableview with several cells of this type, if this is the case you need a custonTableViewCell where you put this code. the buttons respond to a #IBAction that hide the buttons and call a delegate in his UITableViewController.
understand your custonTableViewCell like a viewController for each cell
add this in your custon cell and point the button
// IBAction for buttons
#IBAction func buttonPress(sender: UIButton){
leftButton.hidden = true
rightImage.hidden = true
self.delegate?.buttonPress(sender.tag)
}
add this before your custon cell class definition
protocol CustomTableViewCellDelegate {
func buttonPress(tag: Int)
}
and this after:
var delegate : CustomTableViewCellDelegate?
and in your tableviewcontroller
class TableViewController: UITableViewController, CustomTableViewCellDelegate
and your new func in some place
func buttonPress(tag: Int){
print(tag)
}

How do I write to data in the TableView from a custom UITableViewCell

I have a UITableView that populates “Characteristic” data from HomeKit. The UITableView uses a custom UITableViewCell. The cell has a label and a switch. The cell #IBOutlet and #IBAction work properly allowing me to view the label and toggle/animate the switch in all cells. However, I need the switch to write to the Data Source in the UITableView and I do not know how to reference/access the data from the UITableView in the custom cell. I have determined how to get the indexPath of the selected cell.
I know there is a simple answer here ….. please help this iOS/XCode/Swift beginner.
import UIKit
import HomeKit
class CellServicesCharacteristics: UITableViewCell {
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var switch1: UISwitch!
#IBAction func switch1Act(sender: UISwitch) {
var cell = sender.superview?.superview as! CellServicesCharacteristics
var tableView = cell.superview?.superview as! UITableView
let indexPath = tableView.indexPathForCell(cell) as NSIndexPath!
// How do I reference the Data Source from the TableView
// so I can write to the Data Source?
if switch1.on {
label2.text = "On"
// write to data source in tableview
} else {
label2.text = "Off"
// write to data source in tableview
}
}
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
}
}
Go in to the didSelectRowAtIndexPath over there you will get that
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!){
println("Here is your selected indexPath \(indexPath.row)")
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
There are many approach to do that.
Your Task: To perform operation on HMCharacteristic object when switch is toggle.
1st approach
I - Create property of HMCharacteristic type in your custom cell.
II - Assign HMCharacteristic object in Tableview's cellForRowAtIndexPath.
III - In your custom cell class you are able to access object of HMCharacteritic class.
IV - On switch1Act() method call you can perform action to writeValue() method of HMCharacteristic
2nd approach
I - You can define delegate in Customcell class and implement the delegate in UITableview's class.
II - Call this delegate in switch1Act () method call and pass appropiate index.
III - In your Tableview's implementation class, the delegate method will call. You can get HMCharacteristic from your char array to perform any operation on the Characteristic.
3rd approach
I - You can implement switch1Act() method in Tableview's class itself by setting target for your customcell's switch object.
II - You will receive method call in Tableview's class so no need to pass HMCharacteristic as property

keep UISwitch state of a prototype cell when changing ViewControllers

I have a UITableViewCell subclass where I have connected a UISwitch from a custom prototype cell. (data are passed in the Table View from a previous ViewController)
When I Change view controllers the state of the UISwitchchanges back to default
I need some way to remember the state of the switch while navigating through the app.
I have searched a few other topics, but nothing seemed to fall in my case.
Here is the code:
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var myStaticSwitch: UISwitch!
#IBOutlet weak var cellLabel: UILabel!
#IBAction func mySwitch(sender: UISwitch) {
if myStaticSwitch.on {
self.cellLabel.text = "on"
//Do other things
}
else {
self.cellLabel.text = "off"
//Do other things
}
}
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
}
}
You should have a model object that is used to determine the state of the UI representing it. This object can be saved to disk, persisted with Core Data, or even synced to a remote web service.
When you next encounter a need to display any UI related to the object, you can always check its properties to determine what to show. Your UI action method then simply updates the model representation:
#IBAction func mySwitch(sender: UISwitch) {
myModelObject.enabled = myStaticSwitch.on
}
The UI (e.g., your table cell) then looks for changes to enabled and updates the cellLabel as needed.
here is the code. Now I need a way to refer to each Switch separately and not as a whole.
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var myStaticSwitch: UISwitch!
#IBAction func mySwitch(sender: UISwitch) {
myStaticSwitch.on = (sender as UISwitch).on //Bool
NSUserDefaults.standardUserDefaults().setBool(myStaticSwitch.on, forKey: "autoAdjustSettings")
NSUserDefaults.standardUserDefaults().synchronize()
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
myStaticSwitch.on = NSUserDefaults.standardUserDefaults().boolForKey("autoAdjustSettings")
// Configure the view for the selected state
}
}

Resources