TableView with multiple cell - swift

I'm calling in two separate data in my table. I can change the first call to the data, for example, I can use the switch button. But I can't use the switch button of the data I added in the second, so I can't use the didSelectRowAt property of the data. I can't use the switch button of deviceitemnew, but I can't use didSelectRowAt. So the cell in the code.buttonNew. I can't use the addTarget feature. Probably " return items."count " is a matter of concern.
Click on the button above the photo, click on the button below.
var items: [Device] = []
var itemsnew: [NewDevice] = []
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DeviceTableViewCell
if newdevicechipnumber.isHidden == false {
let deviceItemNew: NewDevice = itemsnew[indexPath.row]
cell.new = deviceItemNew
cell.titleNew.text = deviceItemNew.titleNew
cell.title1New.text = deviceItemNew.placesNew
cell.titlesaatNew.text = deviceItemNew.timeNew
cell.buttonNew.isOn = deviceItemNew.stateNew
cell.buttonNew.addTarget(self, action: #selector(refreshDataNew), for: .touchUpInside)
return cell
}
let deviceItem: Device = items[indexPath.row]
cell.badgeColor = UIColor.flatLime
cell.badgeTextColor = .white;
cell.badgeFontSize = 13;
cell.badgeString = deviceItem.time
cell.badgeOffset = CGPoint(x:70.0, y:50.0)
cell.deviceItem = deviceItem
cell.title.text = deviceItem.title
cell.title1.text = deviceItem.places
cell.titlesaat.text = deviceItem.time
cell.button.isOn = deviceItem.state
cell.button.addTarget(self, action: #selector(refreshData), for: .touchUpInside)
tablerow = String (indexPath.row)
cell.tablerow1 = tablerow
cell.backgroundColor = UIColor(white: 1, alpha: 0.09)
return cell
}

Related

Hide or Delete first row/cell in indexPath

I try to hide or start the indexPath.row at 1. how can i achieved that ?. I already reversed the indexPath and make the count on numberOfRowsInSection - 1, So the list start from the buttom, but when i clicked on the list the content still not changed according to the reversed indexPath.row
Here is my code
extension PaymentMethodViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return paymentMethod.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = paymentMethod[indexPath.row]
switch indexPath {
case indexPathForSelected:
guard let cell = tableView.dequeueReusableCell(withIdentifier: ConstantsIdentifier.paymentMethodCellId,
for: indexPath) as? PaymentMethodCell else {
return UITableViewCell()
}
cell.layoutIfNeeded()
cell.setNeedsLayout()
cell.paymentLbl.text = data.paymentGroupTitle
cell.subLbl.text = selectedPayment.title
cell.descriptionLabel.text = selectedPayment.description
cell.phoneNumberTextField.addTarget(self, action: #selector(textFieldDidChange(sender:)), for: .editingChanged)
cell.phoneNumberTextField.isHidden = selectedPayment.title == ConstantsText.titleOVO ? false : true
cell.phoneNumberTextField.textContentType = .telephoneNumber
cell.phoneNumberTextField.keyboardType = .phonePad
cell.phoneNumberTextField.delegate = self
selectedPayment.code == ConstantsPaymentMethod.defaultPaymentCode ? cell.withSeparator() : cell.removeSeparator()
cell.rightIcon.image = selectedPayment.code == ConstantsPaymentMethod.defaultPaymentCode ? UIImage(named: ConstantsImage.ovalTick) : UIImage(named: ConstantsImage.arrowRight)
cell.rightIcon.contentMode = .scaleAspectFit
if selectedPayment.code == ConstantsPaymentMethod.defaultPaymentCode {
hideCellDesc(cell, true)
} else {
hideCellDesc(cell, false)
}
let imageUrl = URL(string: selectedPayment.logo?.lowres ?? "")
if let objectPayment = paramCheckout?["payment"] as? NSDictionary, let ccNumber = objectPayment["cardNumber"] as? String, !ccNumber.isEmpty {
cell.paymentImg.image = UIImage(named: getImageCC(ccName: getTypeCreditCard(ccNumber: ccInfo?.ccNumber ?? "")))
} else {
cell.paymentImg?.sd_setImage(with: imageUrl, placeholderImage: UIImage(named: ConstantsImage.placeholder), options: .highPriority, completed: nil)
}
return cell
default:
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: ConstantsIdentifier.defaultIndentifier, for: indexPath)
cell.textLabel?.text = data.paymentGroupTitle
cell.textLabel?.numberOfLines = 2
cell.textLabel?.font = UIFont.karlaRegular
let image = UIImageView(image: UIImage(named: ConstantsImage.arrowRight))
cell.accessoryView = image
cell.selectionStyle = .none
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPathForSelected == indexPath && selectedPayment.title == ConstantsText.titleOVO {
return Constant.SelectedHeight + 30
}
if indexPathForSelected == indexPath && selectedPayment.code == ConstantsPaymentMethod.creditCard {
return Constant.CellHeight
}
return indexPathForSelected == indexPath ? Constant.SelectedHeight + 30 : Constant.CellHeight
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return Constant.HeaderHeight
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return ConstantsText.titlePaymentMethod
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
view.tintColor = UIColor.white
let header = view as! UITableViewHeaderFooterView
header.textLabel?.font = UIFont.karlaBold
header.textLabel?.textColor = UIColor.mainBlue
}
}
Please help me, Thanks
Firstly add UITableViewDelegate, I think this is the problem:
extension PaymentMethodViewController: UITableViewDataSource, UITableViewDelegate {}
and
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}

How to disable/enable notifications in tablewiew by using UISwitch in Swift

I am working on a location-based reminder app. I show all reminders that user created on a table view. I have also UISwitch on every cell. I want that UISwitch disables/enables reminders individually, not all notifications. I couldn't figure it out.
extension MainViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! itemTableViewCell
let item = self.items![indexPath.row]
cell.itemTitle?.text = item.itemName
cell.itemSubTitle?.text = item.itemDescription
//switch
let swicthView = UISwitch(frame: .zero)
swicthView.onTintColor = UIColor (named: "DingerBlue")
swicthView.setOn(true, animated: true)
swicthView.tag = indexPath.row
swicthView.addTarget(self, action: #selector(self.SwitchBtn(_:)), for: .valueChanged)
cell.accessoryView = swicthView
let itemToRemove = self.items![indexPath.row]
let notifToRemove: String = itemToRemove.notifID!
return cell
}
#objc func switchDidChanged(_ sender: UISwitch){
print("Switch value is \(sender.isOn)")
if(sender.isOn){
print("on")
UIApplication.shared.registerForRemoteNotifications()
}
else{
print("Off")
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notifToRemove])
}
}
}
I believe your code is not working because cells are reused and actions on specific cells should be handled from the cell class rather than from ViewController. Move this code into the UITableViewCell code.
let swicthView = UISwitch(frame: .zero)
swicthView.onTintColor = UIColor (named: "DingerBlue")
swicthView.setOn(true, animated: true)
swicthView.tag = switchViewTag!
swicthView.addTarget(self, action: #selector(self.SwitchBtn(_:)), for: .valueChanged)
#objc func switchDidChanged(_ sender: UISwitch){
print("Switch value is \(sender.isOn)")
if(sender.isOn){
print("on")
UIApplication.shared.registerForRemoteNotifications()
}
else{
print("Off")
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notifToRemove])
}
}
and add a new property in the UITableViewCell
weak var switchViewTag: Int?
Modify your cellForRowAt delegate method to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! itemTableViewCell
let item = self.items![indexPath.row]
cell.itemTitle?.text = item.itemName
cell.itemSubTitle?.text = item.itemDescription
cell.switchViewTag = indexPath.row
return cell
}

add TestField in new row When Button Touhed swift

there is a table view and i create a button in Second cell . i handled Button Touch event with protocol .i want to add a empty text field in new row at current section Exactly below of phone number text field when add button touched but i cant handle it .
table view cell :
protocol InsertTableCellDelegate {
func insertTableCellDelegate_addrowbtn(sender:InsertTableCell1)
}
class InsertTableCell1: UITableViewCell {
var delegate : InsertTableCellDelegate?
#IBOutlet weak var tbCreateRow: UITableView!
#IBOutlet weak var txtPhoneNumber: JVFloatLabeledTextField!
override func awakeFromNib() {
super.awakeFromNib()
}
#IBAction func btn_Add_DidTouch(_ sender: Any) {
if let delegate = self.delegate
{
delegate.insertTableCellDelegate_addrowbtn(sender: self)
}
}
}
table view Delegates :
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell0 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell0") as! InsertTableCell0
return cell0
}else if indexPath.section == 1 {
//this section should handle add textfield in new row when text button touhed
let cell1 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell1") as! InsertTableCell1
cell1.delegate = self
return cell1
}else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell2") as! InsertTableCell2
cell2.txtEmail.text = strEditEmail
return cell2
}
}
//protocol of button :
func insertTableCellDelegate_addrowbtn(sender: InsertTableCell1) {
print("touched")
}
numberOfRowsInSection have fixed number of cell. First you need to create a
dynamic dataSource.
sample code :
var dataSource : [Int] = Array.init(repeating: 1, count: 3)
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell0 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell0") as! InsertTableCell0
return cell0
}else if indexPath.section == 1 {
//this section should handle add textfield in new row when text button touhed
let cell1 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell1") as! InsertTableCell1
cell1.delegate = self
return cell1
}else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell2") as! InsertTableCell2
cell2.txtEmail.text = strEditEmail
return cell2
}
}
//protocol of button :
func insertTableCellDelegate_addrowbtn(sender: InsertTableCell1) {
dataSource[1] = dataSource[1] + 1
tableView.reloadData() // or you can use beginUpdates() and endUpdates()
}
Sample of code for add new Row when click on add button in Section
//Create outlet for table view
#IBOutlet weak var currentInsetTableView: UITableView!
//Declare these variable
let reuseInsetCellIdentifier = "insertCell";
let titleSection = ["Add Phone", "Add Email"]
var arrayForCellInSection = Array<Any>()
//Add this code in viewDidLoad()
currentInsetTableView.delegate = self
currentInsetTableView.dataSource = self
currentInsetTableView.estimatedRowHeight = 200
currentInsetTableView.rowHeight = UITableView.automaticDimension
currentInsetTableView.register(UINib(nibName: "CurrentInsertTableViewCell", bundle: nil), forCellReuseIdentifier: reuseInsetCellIdentifier)
arrayForCellInSection = Array.init(repeating: 1, count: titleSection.count)
//Implematation of UITablewView Delegate
func numberOfSections(in tableView: UITableView) -> Int {
return titleSection.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayForCellInSection[section] as! Int
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseInsetCellIdentifier, for: indexPath)
as! CurrentInsertTableViewCell
cell.backgroundColor = UIColor.black
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
headerView.backgroundColor = UIColor.black
let buttonX = 10
let buttonY = 10
let buttonWidth = 30
let buttonHeight = 30
let button = UIButton(type: .system)
let imgAdd = UIImage(named: "Add")
button.setImage(imgAdd, for: .normal)
button.addTarget(self, action: #selector(buttonClickedForInsertRowInSection(sender:)), for: .touchUpInside)
button.frame = CGRect(x: buttonX, y: buttonY, width: buttonWidth, height: buttonHeight)
button.tag = section
headerView.addSubview(button)
let label = UILabel()
label.frame = CGRect.init(x: button.frame.size.width + CGFloat((2 * buttonX)), y: CGFloat(buttonY), width: headerView.frame.width - button.frame.size.width + CGFloat((3 * buttonX)), height: headerView.frame.height - CGFloat((2 * buttonY)))
label.text = titleSection[section]
label.textColor = UIColor.white
headerView.addSubview(label)
return headerView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
//CurrentInsertTableViewCell Desing
//Final Result: When we press two times on first section add button & one times on second section add button

iam begineeer to the swift.i have created the table view when xml parsing is done .its showing me only height of the cell.blank cells

I am new to the Swift language and just a beginner, I have created tableview. I want to show the data whereas when I'm running the code it shows me empty cells. I have checked the delegates and connections .
func numberOfSections(in dashboardtable: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 114
}
func tableView(_ dashboardtable: UITableView, numberOfRowsInSection section: Int) -> Int {
return toddler.count
}
func tableView(_ dashboardtable: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = dashboardtable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DashTableViewCell
cell.cname.text = toddler[indexPath.row]["ChildName"] as? String
cell.cage.text = toddler[indexPath.row]["Age"] as? String
cell.childc.text = toddler[indexPath.row]["Class"] as? String
if let base64 = toddler[indexPath.row]["Photo"] as? String,let data = Data.init(base64Encoded: base64), let image = UIImage.init(data: data){
cell.childimage.image = image
} else {
cell.childimage.image = UIImage.init(named: "")
}
cell.backgroundColor = UIColor.white
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 8
cell.clipsToBounds = true
//to display the whole details
print(indexPath.row)
return cell
}
If you want hide lines in blank tableView
use this:
tableView.separatorStyle = .none
be sure set delegate and datasource and call reloadData

“Thread 1: Fatal error: Index out of range in Swift” from TableView

I want to pull the data from chipnumber2 and chipnumber. I want to collect the two in a table, but there's a problem. How do I draw data from two text tables? "let deviceItem: Device3New = itemsNew[indexPath]".I'm getting this problem on the row. In short, I want to draw the data in Device3New and device3 to the same table. How can I do that?
class NewMainTableViewController: UITableViewController {
var items: [Device3] = []
var itemsNew: [Device3New] = []
let cellId: String = "cellId"
let cellIdNew: String = "cellIdNew"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(DeviceTableViewCell2.self, forCellReuseIdentifier: cellId)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if !chipnumber2.text!.isEmpty {
let cellNew = tableView.dequeueReusableCell(withIdentifier: cellIdNew, for: indexPath) as! DeviceTableViewCell2
let deviceItem: Device3New = itemsNew[indexPath.row]
cellNew.badgeColor = UIColor.flatLime
cellNew.badgeTextColor = .white;
cellNew.badgeFontSize = 13;
cellNew.badgeString = deviceItem.time
cellNew.badgeOffset = CGPoint(x:30.0, y:63)
cellNew.textLabel?.text = deviceItem.title
cellNew.deviceItem3New = deviceItem
cellNew.titleNew.text = deviceItem.title
cellNew.title1New.text = deviceItem.places
cellNew.titlesaatNew.text = deviceItem.time
cellNew.buttonNew.isOn = deviceItem.state
cellNew.tablerow = String (indexPath.row)
cellNew.backgroundColor = UIColor(white: 1, alpha: 0.09)
return cellNew
}
if !chipnumber.text!.isEmpty {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DeviceTableViewCell2
let deviceItem: Device3 = items[indexPath.row]
cell.badgeColor = UIColor.flatLime
cell.badgeTextColor = .white;
cell.badgeFontSize = 13;
cell.badgeString = deviceItem.time
cell.badgeOffset = CGPoint(x:30.0, y:63)
cell.textLabel?.text = deviceItem.title
cell.deviceItem3 = deviceItem
cell.title.text = deviceItem.title
cell.title1.text = deviceItem.places
cell.titlesaat.text = deviceItem.time
cell.button.isOn = deviceItem.state
cell.tablerow = String (indexPath.row)
cell.backgroundColor = UIColor(white: 1, alpha: 0.09)
return cell
}
return UITableViewCell()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !chipnumber2.text!.isEmpty {
return itemsNew.count + items.count
} else if !chipnumber.text!.isEmpty {
return items.count
}
return 0
}
The problem is that cellForRowAt it trying to handle a scenario where there are two arrays, but both deviceItem assignments are using the same indexPath.row as an index within the respective array. But if items has two items and newItems has three, the cellForRowAt will called five times, with indexPath.row values ranging between 0 through 4. But you’re using indexPath.row in both arrays, and so you’re going to go beyond the bounds of the array for one or both of items and newItems.
The easiest solution is to have two sections, one for items and another for newItems. That gets you out of the business of having to figure out which indexPath belongs to which array:
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return itemsNew.count
} else {
return items.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cellNew = tableView.dequeueReusableCell(withIdentifier: cellIdNew, for: indexPath) as! DeviceTableViewCell2
let deviceItem = itemsNew[indexPath.row]
...
return cellNew
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DeviceTableViewCell2
let deviceItem = items[indexPath.row]
...
return cell
}
}
Note, I’m not looking at the text fields. The above assumes that you’ll just populate both arrays (and call tableView.reloadData()).
it because you add items and ItemsNew for define the tableViewCell, you should use just one of them or use a protocol for sync them as well.
so here is the correct code
class NewMainTableViewController: UITableViewController {
var items: [Device3] = []
var itemsNew: [Device3New] = []
var sumItems: []
let cellId: String = "cellId"
let cellIdNew: String = "cellIdNew"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(DeviceTableViewCell2.self, forCellReuseIdentifier: cellId)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if !chipnumber2.text!.isEmpty {
let cellNew = tableView.dequeueReusableCell(withIdentifier: cellIdNew, for: indexPath) as! DeviceTableViewCell2
let deviceItem: Device3New = itemsNew[indexPath.row]
cellNew.badgeColor = UIColor.flatLime
cellNew.badgeTextColor = .white;
cellNew.badgeFontSize = 13;
cellNew.badgeString = deviceItem.time
cellNew.badgeOffset = CGPoint(x:30.0, y:63)
cellNew.textLabel?.text = deviceItem.title
cellNew.deviceItem3New = deviceItem
cellNew.titleNew.text = deviceItem.title
cellNew.title1New.text = deviceItem.places
cellNew.titlesaatNew.text = deviceItem.time
cellNew.buttonNew.isOn = deviceItem.state
cellNew.tablerow = String (indexPath.row)
cellNew.backgroundColor = UIColor(white: 1, alpha: 0.09)
return cellNew
}
if !chipnumber.text!.isEmpty {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DeviceTableViewCell2
let deviceItem: Device3 = items[indexPath.row]
cell.badgeColor = UIColor.flatLime
cell.badgeTextColor = .white;
cell.badgeFontSize = 13;
cell.badgeString = deviceItem.time
cell.badgeOffset = CGPoint(x:30.0, y:63)
cell.textLabel?.text = deviceItem.title
cell.deviceItem3 = deviceItem
cell.title.text = deviceItem.title
cell.title1.text = deviceItem.places
cell.titlesaat.text = deviceItem.time
cell.button.isOn = deviceItem.state
cell.tablerow = String (indexPath.row)
cell.backgroundColor = UIColor(white: 1, alpha: 0.09)
return cell
}
return UITableViewCell()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !chipnumber2.text!.isEmpty {
return itemsNew.count //+ items.count
} else if !chipnumber.text!.isEmpty {
return items.count
}
return 0
}