Set UITableView rows as selected if contained in an array - swift

I have data stored in a realm database. I retrieve the information from the database and place it in an array. I then search through the array and set the cell to selected if it is contained in the array.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:SubjectsTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! SubjectsTableViewCell
var subject: Subjects!
subject = Subjects[Int(indexPath.row)]
cell.subject.text = subject.subjectTitle
if chosenSubjects.contains(subject.subjectTitle) {
cell.selected = true
cell.accessoryType = .Checkmark
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
cell.highlighted = true
} else {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
}
return cell
}
Unfortunately, the above code is giving me some strange results. Sometimes the cells are highlighted and display a checkmark, sometimes the first cell in the table is unhighlighted, but displays a checkmark. Sometimes I have to press the cell twice to deselect. Note, I have also set the didSelectRowAtIndexPath and didDeselectRowAtIndexPath as follows:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get the row data for the selected row
self.tableView.allowsMultipleSelection = true
let cell:SubjectsTableViewCell = tableView.cellForRowAtIndexPath(indexPath) as! SubjectsTableViewCell
cell.accessoryType = .Checkmark
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
// Get the row data for the selected row
self.tableView.allowsMultipleSelection = true
let cell:SubjectsTableViewCell = tableView.cellForRowAtIndexPath(indexPath) as! SubjectsTableViewCell
cell.accessoryType = .None
}

I believe that this can occur because you are reusing cells with your line
let cell:SubjectsTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! SubjectsTableViewCell
Instead, try doing something like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:SubjectsTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! SubjectsTableViewCell
var subject: Subjects!
subject = Subjects[Int(indexPath.row)]
cell.subject.text = subject.subjectTitle
if chosenSubjects.contains(subject.subjectTitle) {
cell.selected = true
cell.accessoryType = .Checkmark
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
cell.highlighted = true
} else {
cell.selected = false
cell.accessoryType = .None
cell.highlighted = false
tableView.deselectRowAtIndexPath(indexPath, animated: false)
}
return cell
}
Hope this helps; let me know if it doesn't!
Edit:
I just noticed that within your select and deselect tableview functions, you don't actually update your chosenSubjects array for the given row. You need to update this before you call cellForRowAtIndexPath; otherwise, the if condition (in your cellForRowAtIndexPath) will fail - thus leading to the weird behaviour!
Try this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get the row data for the selected row
self.tableView.allowsMultipleSelection = true
var subject: Subjects! = Subjects[Int(indexPath.row)]
chosenSubjects.addObject(subject.subjectTitle)
let cell:SubjectsTableViewCell = tableView.cellForRowAtIndexPath(indexPath) as! SubjectsTableViewCell
cell.accessoryType = .Checkmark
}
and this:
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
// Get the row data for the selected row
self.tableView.allowsMultipleSelection = true
var subject: Subjects! = Subjects[Int(indexPath.row)]
chosenSubjects = chosenSubjects.filter() { $0 != subject.subjectTitle }
let cell:SubjectsTableViewCell = tableView.cellForRowAtIndexPath(indexPath) as! SubjectsTableViewCell
cell.accessoryType = .None
}

var userCLient = string is an empty string array declare..
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedRow:UITableViewCell = tableView.cellForRow(at: indexPath)!
if selectedRow.accessoryType == UITableViewCellAccessoryType.none{
selectedRow.accessoryType = UITableViewCellAccessoryType.checkmark
selectedRow.tintColor = UIColor.green
var dict = arrRes[(indexPath as NSIndexPath).row]
let EmpID = dict["user_id"] as? Int
self.userCLient.append(String(describing: EmpID!))
print("Employee:\(self.userCLient)")
}
else{
selectedRow.accessoryType = UITableViewCellAccessoryType.none
var dict = arrRes[(indexPath as NSIndexPath).row]
let EmpID = dict["user_id"] as? Int
if let index = self.userCLient.index(of: String(describing: EmpID!)) {
self.userCLient.remove(at: index)
}
print("Employee:\(self.userCLient)")
}
}

Related

selecting cell in section one authomatically selecting cell in section two swift

I have an application where I have two sections the issue I have now is if I select an item in section 1, it automatically selects a cell in section 2 which is not suppose to be. I want Items to be selectable in section 1 without affecting section two.
below is my selection
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.section {
case 0:
showCustomDialog(subD: sub[indexPath.row])
case 1:
let cell = tableView.cellForRow(at: indexPath) as! VasListCell
cell.checkBox.setOn(true, animated: true)
default: break
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
switch indexPath.section {
case 1:
let cell = tableView.cellForRow(at: indexPath) as! VasListCell
cell.checkBox.setOn(false, animated: true)
default: break
}
}
where I am using the selected index
func selectedIndex(viewcontroller: UIViewController) {
let selectedRows = tableView.indexPathsForSelectedRows
guard let vasRow = selectedRows?.map ({ vas[$0.row] }) else { return }
selectedVasData = vasRow
let vasData = selectedVasData
let subData = selectedSubData
let vcr = viewcontroller as! CheckoutVC
vcr.vas = vasData
vcr.sub = subData
let tot1 = subData.compactMap {$0.price}
let tot2 = vasData.compactMap {$0.amount}
let tot = tot1 + tot2
let reduced = tot.compactMap(Double.init).reduce(0, +)
vcr.tableView.reloadData()
self.present(viewcontroller, animated: true, completion: nil)
print("CELL INDEX vas \(StaticFunc.convertDoubleToCurrency(amount: reduced))")
}

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.

xCode TableView search results do not display correctly as cellForRowAt still calls upon the original, unfiltered array

I have just finished adding a search bar to my TableView. It everything works perfectly, except the data displayed in the search results still shows the objects from the original, unfiltered array (although, when I click on the results they take me to the correct DetailView of the object for which I searched).
So the search logic is working, I just am not receiving a correct visual display of the search results.
I believe the issue arises in my cellForRowAt function, in which I attempt to determine whether the cell is filled with data from the original array or the search results. This line is marked with a caution error (the yellow one!) that reads 'Initialization of immutable value 'location' was never used; consider replacing with assignment to '_' or removing it'. However, I am unsure of how else to write this line.
Please see the relevant search code below (with the error line marked using a comment - it is almost at the very bottom of this code).
var locations = [Location]()
var searchController:UISearchController!
var searchResults = [Location]()
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
tableView.tableHeaderView = searchController.searchBar
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
self.tableView.reloadData()
}
func filterContent(for searchText: String) {
searchResults = locations.filter({ (location) -> Bool in
if let name = location.name {
let isMatch = name.localizedCaseInsensitiveContains(searchText)
return isMatch
}
return false
})
}
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text {
filterContent(for: searchText)
tableView.reloadData()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController != nil && searchController.isActive {
return searchResults.count
} else {
return locations.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! LocationTableViewCell
// The following line is where I receive the error, as I attempt to determine whether the app should get the result from the filtered search result
let location = (searchController.isActive) ? searchResults[indexPath.row] : locations[indexPath.row]
cell.nameLabel.text = locations[indexPath.row].name
cell.thumbnailImageView.image = UIImage(named: locations[indexPath.row].image)
cell.locationLabel.text = locations[indexPath.row].location
cell.typeLabel.text = locations[indexPath.row].type
cell.accessoryType = locations[indexPath.row].isVisited ? .checkmark : .none
return cell
}
You're never using location. Change your code below that line to use it:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! LocationTableViewCell
let location = (searchController.isActive) ? searchResults[indexPath.row] : locations[indexPath.row]
//use the location variable you just set to set the cell's properties
cell.nameLabel.text = location.name
cell.thumbnailImageView.image = UIImage(named: location.image)
cell.locationLabel.text = location.location
cell.typeLabel.text = location.type
cell.accessoryType = location.isVisited ? .checkmark : .none
return cell
}

Swift - How can I select multiple rows in tableview without segue

My development environment is swift3, xcode8.
I'm making a list app like Apple's message app.
When I select the list in the table view, I go to the detail page (through the seg) and now I want to implement multiple delete functions, but there's a problem. When I edit mode, I can see the selection window, but if I select that selection window, just go to the detail page.
Maybe before going to the detail page through Seg. I think I should make it a multiple choice. What should I do?
Make sure you conform something like below code;
class TableviewController:UITableViewController{
override func viewDidLoad() {
super.viewDidLoad()
var isMultipleSelectionActive = false
var selectedItems: [String: Bool] = [:]
tableView.allowsMultipleSelectionDuringEditing = true
tableView.setEditing(true, animated: false)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedItem = items.objectAtIndex(indexPath.row)
//add to selectedItems
selectedItems[selectedItem] = true
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let selectedItem = items.objectAtIndex(indexPath.row)
// remove from selectedItems
selectedItems[selectedItem] = nil
}
func getStatusOfSelectedItems() {
for item in selectedItems {
println(item)
}
}
//You should override shouldPerformSegueWithIdentifier and return false if isMultipleSelectionActive is true
override func shouldPerformSegue(withIdentifier identifier: String?, sender: Any?) -> Bool {
if let identifierName = identifier {
if identifierName == "NameOfYourSegueIdentifier" {
if isMultipleSelectionActive {
return false
}
}
}
return true
}
}
This code used to select the multiple row
class TableViewController: UITableViewController
{
var lastSelectedIndexPath = NSIndexPath(forRow: -1, inSection: 0)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath)
// Configure the cell...
cell.textLabel!.text = "row: \(indexPath.row)"
if cell.selected
{
cell.selected = false
if cell.accessoryType == UITableViewCellAccessoryType.None
{
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}
else
{
cell.accessoryType = UITableViewCellAccessoryType.None
}
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath)
if cell!.selected
{
cell!.selected = false
if cell!.accessoryType == UITableViewCellAccessoryType.None
{
cell!.accessoryType = UITableViewCellAccessoryType.Checkmark
}
else
{
cell!.accessoryType = UITableViewCellAccessoryType.None
}
}
}

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