How to solve duplicated and repeated check in UITableView checklist? - swift

I'm setting up survey screen consists of table view so that each cell has table view of checkboxes the problem is that when I check box and scroll down I find that another cell dequeued with checkbox selected.
I have tried to change selection state in prepare for reuse but didn't work
this code for checkbox table view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = taskActionOptionTableView.dequeueReusableCell(withIdentifier: Constants.TASK_CHOOSE_OPTIONCELL_ID, for: indexPath) as? TaskChooseOptionCell
if taskResponseActionId == nil {
taskResponseAction = TaskResponseAction()
}
cell?.taskCheckBox.boxType = .circle
cell?.taskCheckBox.markType = .radio
cell?.taskCheckBox.boxLineWidth = 2
cell?.delegate = self
if cell?.taskCheckBox.checkState == .checked {
print("checked")
}
if taskAction?.taskDependentActions.count != 0 {
cell?.scoreOperator = taskAction?.taskDependentActions[indexPath.section].scoreOperator
cell?.scoreNumberValue = taskAction?.taskDependentActions[indexPath.section].scoreNumberValue
}
cell?.taskActionOptionScoreValue = taskAction?.taskActionOptions[indexPath.row].taskActionOptionScoreValue
if cell == nil {
cell = TaskChooseOptionCell.customCell
}
if isDependent {
cell?.taskDepActionOption = taskDependentActionOptions?[indexPath.row]
return cell!
} else {
cell?.taskActionOption = taskActionOptions?[indexPath.row]
return cell!
}
}
And this for the main table view cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let id = task?.taskActions[indexPath.section].actionTypeId
let cellType = TaskActionType.allCases.filter {
return $0.id == id
}.first
guard let cellDescType = cellType else { return UITableViewCell() }
switch cellDescType {
case .date:
let dateCell = tableView.dequeueReusableCell(withIdentifier: Constants.DATE_CELL_ID, for: indexPath) as! DateCell
dateCell.taskMaterial = taskActionsOnMaterialArray[indexPath.row].material
return dateCell
case .multiChoice:
let multiChoiceCell = tableView.dequeueReusableCell(withIdentifier: Constants.MULTI_CHOOSE_CELL_ID, for: indexPath) as! MultiChooseCell
multiChoiceCell.delegate = self
multiChoiceCell.taskMaterial = task?.taskRestrictedMaterials[indexPath.row]
multiChoiceCell.taskAction = task?.taskActions[indexPath.section]
multiChoiceCell.taskActionOptions = Array((task?.taskActions[indexPath.section].taskActionOptions)!)
return multiChoiceCell
case .text:
let textCell = tableView.dequeueReusableCell(withIdentifier: Constants.TEXT_CELL_ID, for: indexPath) as! TextViewCell
return textCell
case .singleChoice:
let singleChoiceCell = tableView.dequeueReusableCell(withIdentifier: Constants.SINGLE_CHOICE_CELL_ID, for: indexPath) as! SingleChoiceCell
singleChoiceCell.delegate = self
singleChoiceCell.taskMaterial = task?.taskRestrictedMaterials[indexPath.row]
singleChoiceCell.taskAction = task?.taskActions[indexPath.section]
singleChoiceCell.taskActionOptions = Array((task?.taskActions[indexPath.section].taskActionOptions)!)
return singleChoiceCell
case .number:
let numberCell = tableView.dequeueReusableCell(withIdentifier: Constants.NUMBER_CELL_ID, for: indexPath) as! NumberCell
return numberCell
}
}

In your data model you can add a variable like var done : Bool = " " and set it to false initially and toggle it on didSelectRow to true or false accordingly and check this variable on the time of setting accessoryType. If its true then set it to .checked else set it to .none.

Related

Checkbox not working separately in swift. How can I make it separate?

I have problem about checkbox in swift. I use M13Checkbox, found in github. In my app when I click at index 0 cell's checkbox, all even numbers(index) cells checkboxs checked. And also when I click at index 1 cell's checkbox all odd numbers(index) cell's checkboxs get checked. I can't find any reason for that Can anybody help me?
Here my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: sipCellId, for: indexPath) as! sipCell
var searched: String?
if isSearching {
searched = filteredArray[indexPath.row]
}else{
searched = self.orderId[indexPath.row]
}
cell.orderIdLabel.text = searched
//cell.orderIdLabel.text = self.orderId[indexPath.row]
cell.detailLabel.text = self.newDatas[indexPath.row]
cell.alindiLabel.text = "Alındı: "
cell.temizlemedeLabel.text = "Temizlemede: "
cell.teslimEdildiLabel.text = "Teslim edildi: "
cell.kapidaOdemeLabel.text = "Kapıdan alınacak tutar: \(self.ucret[indexPath.row])"
cell.deleteButton.tag = indexPath.row
cell.urunEklemeButton.tag = indexPath.row
cell.uncheckedButtonAlindi.tag = indexPath.row
cell.uncheckedButtonTemizleme.tag = indexPath.row
cell.uncheckedButtonTeslim.tag = indexPath.row
return cell
}
Here my checkbox function:
#objc func checkControlAlindi(sender : M13Checkbox?) {
switch sender!.checkState {
case .checked:
let indexPath = IndexPath(row: (sender!.tag), section: 0)
let cell = tableView.cellForRow(at: indexPath) as! sipCell
print(cell.orderIdLabel.text!)
print("alındı kısmına bastınız... ", (sender!.tag))
break
case .unchecked:
print("unchecked")
break
case .mixed:
//empty...
break
}
}
And here my checkbox:
let uncheckedButtonAlindi: M13Checkbox = {
let button = M13Checkbox()
button.tintColor = .orange
button.boxType = .circle
button.secondaryTintColor = .lightGray
button.boxLineWidth = 4
button.checkmarkLineWidth = 3
button.addTarget(self, action: #selector(ViewController.checkControlAlindi(sender:)), for: UIControl.Event.valueChanged)
return button
}()

Use 2 Table View in the same View Controller (Swift 4)

I have a problem handling 2 tables on the same screen. Every time he keeps crashing. Can someone help me?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: TableViewCellComunicazioni?
if tableView == self.tableViewNotifica {
cell = tableView.dequeueReusableCell(withIdentifier: "cellNotifica", for: indexPath) as? TableViewCellComunicazioni
let dataNotifica = structNotifica[indexPath.row].dateNotifica
let testoNotifica = structNotifica[indexPath.row].textNotifica
cell?.dateNotification.text = "\(date!)"
cell?.textNotification.text = "\(text!)"
return cell!
}
if tableView == self.tableViewInbox {
cell = tableView.dequeueReusableCell(withIdentifier: "cellInbox", for: indexPath) as? TableViewCellComunicazioni
let email = structInbox[indexPath.row].email
let messaggio = structInbox[indexPath.row].messaggio
let data = structInbox[indexPath.row].data
cell?.emailInbox.text = "\(email!)"
cell?.messaggioInbox.text = "\(message!)"
cell?.dataInbox.text = "\(date!)"
return cell!
}
return UITableViewCell()
}
This could be a probable fix for your problem:
Coding Example:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.tableViewNotifica {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellNotifica", for: indexPath) as? TableViewCellComunicazioni
let dataNotifica = structNotifica[indexPath.row].dateNotifica
let testoNotifica = structNotifica[indexPath.row].textNotifica
cell?.dateNotification.text = "\(date!)"
cell?.textNotification.text = "\(text!)"
return cell!
}
if tableView == self.tableViewInbox {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellInbox", for: indexPath) as? TableViewCellComunicazioni
let email = structInbox[indexPath.row].email
let messaggio = structInbox[indexPath.row].messaggio
let data = structInbox[indexPath.row].data
cell?.emailInbox.text = "\(email!)"
cell?.messaggioInbox.text = "\(message!)"
cell?.dataInbox.text = "\(date!)"
return cell!
}
return UITableViewCell()
}
And make sure that you have correct cell identifier for dequeuing.
extension ViewController : UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listmoviesArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == moviesTableView {
let cell = tableView.dequeueReusableCell(withIdentifier: "MovieTableViewCell", for: indexPath) as! MovieTableViewCell
cell.delegate = self
cell.setupCell(listmoviesArray[indexPath.row],indexPath: indexPath)
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "MovieTableViewCell2", for: indexPath) as! MovieTableViewCell
cell.delegate = self
cell.setupCell(listmoviesArray[indexPath.row],indexPath: indexPath)
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == moviesTableView {
// Handle your selection for row.
} else {
//Handle your selection for row.
}
}
}
Above code produces the following output with 2 Tableview.

Checkmark's associated with wrong row in TableView when using SearchBar

I am creating an application where when a User searches for an item in the TableView they can click on it and a checkmark appears next to it. However, say when I select the first item I have searched for and click it then delete my search the checkmark stays on the first row but for a completely different object, I searched for, to begin with (see images below).
When Searching
When not Searching
var searchingArray = [Symptoms]()
var filteredArray = [Symptoms]()
var selectedSymptoms = [Symptoms]()
var clicked = [String]()
var searchingUnderWay = false
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = searchingSymptomsTableView.dequeueReusableCell(withIdentifier: "ExtraSymptoms", for: indexPath) as? ExtraSymptomCell {
let searchingArrays: Symptoms!
if searchingUnderWay {
searchingArrays = self.filteredArray[indexPath.row]
} else {
searchingArrays = self.searchingArray[indexPath.row]
}
cell.updateUI(symptomNames: searchingArrays)
return cell
} else {
return UITableViewCell()
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedRow: Symptoms!
let symptomName: String!
let cell : UITableViewCell = tableView.cellForRow(at: indexPath)!
if searchingUnderWay {
selectedRow = filteredArray[indexPath.row]
symptomName = filteredArray[indexPath.row].name as String
if clicked.contains(symptomName) {
cell.accessoryType = .none
let indexNumber = clicked.index(of: symptomName)
clicked.remove(at: indexNumber!)
if let element = selectedSymptoms.index(where: { $0.name == selectedRow.name }) {
selectedSymptoms.remove(at: element)
}
} else {
clicked.append(symptomName)
cell.accessoryType = .checkmark
searchingSymptomsTableView.reloadData()
selectedSymptoms.append(selectedRow)
}
} else {
selectedRow = searchingArray[indexPath.row]
symptomName = searchingArray[indexPath.row].name as String
if clicked.contains(symptomName) {
cell.accessoryType = .none
let indexNumber = clicked.index(of: symptomName)
clicked.remove(at: indexNumber!)
if let element = selectedSymptoms.index(where: { $0.name == selectedRow.name }) {
selectedSymptoms.remove(at: element)
}
} else {
clicked.append(symptomName)
cell.accessoryType = .checkmark
searchingSymptomsTableView.reloadData()
selectedSymptoms.append(selectedRow)
}
print(clicked)
print(selectedSymptoms)
}
}
I wish for the item I searched using the searchbar to still be checked when you delete the search.
Many thanks
Welcome to TableViewController logic. It seems really strange, but it works correct)
You need to override prepareForReuse() method in your ExtraSymptomCell. And clear all the values your cell contains including accessoryType
override func prepareForReuse() {
super.prepareForReuse()
accessoryType = .none
}
In your tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath):
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = searchingSymptomsTableView.dequeueReusableCell(withIdentifier: "ExtraSymptoms", for: indexPath) as? ExtraSymptomCell {
let symptomName: String!
let searchingArrays: Symptoms!
if searchingUnderWay {
searchingArrays = self.filteredArray[indexPath.row]
symptomName = filteredArray[indexPath.row].name as String
} else {
searchingArrays = self.searchingArray[indexPath.row]
symptomName = filteredArray[indexPath.row] as String
}
cell.updateUI(symptomNames: searchingArrays)
if clicked.contains(symptomName) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
return cell
} else {
return UITableViewCell()
}
}
Since UITableViewCell are reused, the checkmark will appear in a cell when you reload Table Data.
In cellForRowAt set the accessoryType to .none, to remove a previously checked cell checkmark:
let cell : UITableViewCell = tableView.cellForRow(at: indexPath)!
cell.accessoryType = .none
This will remove the check from the previous search.

How to set a segment control to change collection cell item in table view cell?

I created a collection view in table view cell and added a segment control on the navigation bar of the table view. How can I change the collection cell item when the segment outlet and action is on table view controller?
I tried this on table view controller but get this error:
request for number of items before section 2147483647 when there are only 1 sections in the collection view
#IBAction func mySegAction(_ sender: UISegmentedControl) {
switch mySeg.selectedSegmentIndex
{
case 0:
print("0")
case 1:
print("1")
let indexPath = IndexPath()
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CategoryCollectionViewCell
cell.cateLabel.text! = nameArray2[indexPath.row]
default:
break;
}
}
Table view cell controller:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CategoryCollectionViewCell
cell.cateLabel.text! = nameArray[indexPath.row]
// I tried this code but fail
if AddViewController().mySeg?.selectedSegmentIndex == 1 {
cell.cateLabel.text! = nameArray2[indexPath.row]
}
return cell
}
I want to change cateLabel.text! = nameArray[indexPath.row] to nameArray2[indexPath.row] when the Segment is changed, How to do that?
Calling tableView.reloadData() on Action and collectionView.reloadData() on cellForRowAt
#IBAction func mySegAction(_ sender: UISegmentedControl) {
switch mySeg.selectedSegmentIndex{
case 0:
segment = 0
UserDefaults.standard.setValue(segment, forKey:"segment")
UserDefaults.standard.synchronize()
case 1:
segment = 1
UserDefaults.standard.setValue(segment, forKey:"segment")
UserDefaults.standard.synchronize()
default:
break;
}
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 1{
let cell1 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell2", for: indexPath)
return cell1
}else if indexPath.row == 2{
let cell2 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell3", for: indexPath)
return cell2
}else if indexPath.row == 3{
let cell3 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell4", for: indexPath)
return cell3
}else if indexPath.row == 4{
switch segment {
case 0:
let cell4 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell5", for: indexPath) as! AddViewCell
cell4.collectionView.reloadData()
return cell4
case 1:
let cell4 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell5", for: indexPath) as! AddViewCell
cell4.collectionView.reloadData()
return cell4
default:
break
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "AddViewCell1", for: indexPath)
return cell
}
On the table view cell class:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CategoryCollectionViewCell
let segment = UserDefaults().value(forKey: "segment") as! Int
//print("segment here")
//print(segment)
switch segment {
case 0:
cell.cateLabel.text! = nameArray[indexPath.row]
cell.cateImg.image = imageName[indexPath.row]
case 1:
cell.cateLabel.text! = nameArray2[indexPath.row]
cell.cateImg.image = imageName[indexPath.row]
default:
break;
}
return cell
}

How to Set data to second tableview in same Class in swift

How to Set data to second tableview in same Class in swift.I am using two tables in the the same controller one for dropdown and another for listing. I am unable to set data to second table(listing) in class
as else part is not called in cellForRowAtIndexPath. Thanks in Advance
import UIKit
class PunchClockVC: UIViewController , UITableViewDataSource, UITableViewDelegate{
var appdel = UIApplication.sharedApplication().delegate as! AppDelegate
#IBOutlet weak var dropdownTable: UITableView!
#IBOutlet weak var mainTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.mainTable.registerClass(PunchClockCustomCell.self, forCellReuseIdentifier: "PunchClockCustomCell")
self.dropdownTable.registerClass(UITableViewCell.self, forCellReuseIdentifier: "dropdowncell")
self.dropdownTable.hidden = true
}
#IBAction func textFieldTapped(sender: AnyObject) {
if self.dropdownTable.hidden == true {
self.dropdownTable.hidden = false
}
else{
self.dropdownTable.hidden = false
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == dropdownTable {
return jobArrayID.count
}
return 8
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.dropdownTable {
let cell = tableView.dequeueReusableCellWithIdentifier("dropdowncell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = (jobArrayID[indexPath.row] as! String) + "-" + (jobArrayName[indexPath.row] as! String)
return cell
}
else {
let cell1 = tableView.dequeueReusableCellWithIdentifier("PunchClockCustomCell", forIndexPath: indexPath) as! PunchClockCustomCell
if indexPath.row == 0
{
cell1.jobcell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.locationcell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.timecell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.typecell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.jobcell?.textColor = UIColor.blackColor()
cell1.locationcell?.textColor = UIColor.blackColor()
cell1.timecell?.textColor = UIColor.blackColor()
cell1.typecell?.textColor = UIColor.blackColor()
cell1.jobcell?.text = "Job"
cell1.locationcell?.text = "Location"
cell1.timecell?.text = "Time"
cell1.typecell?.text = "Type"
// return cell1
}
else {
cell1.jobcell?.text = "Jobdata"
cell1.locationcell?.text = "Locationdata"
cell1.timecell?.text = "Timedata"
cell1.typecell?.text = "OUT"
// return cell1
}
return cell1
}
}
It's quite simple You need to set it only with cellForRowAtIndexPath method but the main thing to do is you need to code like below
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
if tableView == firstTbaleView
//outlet given to first tableView
{
let cell = tableView.dequeueReusableCellWithReuseIdentifier("cell1", forIndexPath: indexPath) as! cust1TableViewCell
cell.imgView.image = images[indexPath.row]
cell.filtLabel.text = self.filtersCount[indexPath.row]
return cell
}}else {
let cell2 = tableView.dequeueReusableCellWithReuseIdentifier("cell2", forIndexPath: indexPath) as! cust2TableViewCell
cell2.imgview.image = UIImage(named: colPhotos[indexPath.row])
cell2.labl.text = colNames[indexPath.row]
// cell2.layer.borderColor = UIColor.blueColor().CGColor
// cell2.layer.borderWidth = 2.0
return cell2
}
and that's it you can ask me for any help..
Lets make this a little safer:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.dropdownTable {
return jobArray.count
}
else if tableView == self.mainTable {
return = 5
}
//Default return 0. This way if references are broken or change, you won't crash
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.dropdownTable {
let cell = tableView.dequeueReusableCellWithIdentifier("dropdowncell", forIndexPath: indexPath) as! UITableViewCell
//configure your cell
return cell
}
else if tableView == self.mainTable {
let cell = tableView.dequeueReusableCellWithIdentifier("PunchClockCustomCell", forIndexPath: indexPath) as! PunchClockCustomCell
//configure your cell
return cell
}
//Shouln't ever reach here, but again, if we refactor somewhere then we'll see an error show up before here.
return UITableViewCell()
}