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
}
Related
I'm trying to make a filter. I got a tableview. When I click any section, it expands and collapses.
My problem is that when I open and close other sections after clicking on the checkboxes, unselected checkboxes in other sections appear as selected and selected ones are unselected. What should I do? Can you show me some code? Thanks!
https://ibb.co/0htP7Hz // Filter image
var hiddenSections = Set<Int>()
var filtersArray = Set<String>()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "FilterCell", for: indexPath) as? FilterTableViewCell else
{
fatalError("Product Group Cell not found")
}
guard let item = self.filterElementListVM.itemfilterviewmodelAtIndex(indexPath) else {
return UITableViewCell()
}
cell.setupCell(title: item.definition ?? "", buttonTag: item.id ?? 0, filterArray: self.filtersArray)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? FilterTableViewCell {
let selectedFilterItem = self.filterElementListVM.itemfilterviewmodelAtIndex(indexPath)
if cell.buttonCheck.isSelected {
self.filtersArray.remove(String(selectedFilterItem?.definition ?? ""))
} else {
self.filtersArray.insert(String(selectedFilterItem?.definition ?? ""))
}
cell.buttonCheckTap()
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let viewHeader = UIView.init(frame: CGRect.init(x: 0.0, y: 0.0, width: tableView.frame.size.width, height: 67.0))
viewHeader.backgroundColor = .white
let filterVM : FilterViewModel = self.filterElementListVM.filterViewModelAtIndex(section)
let viewFilterHeader : ViewFilter = ViewFilter.init(title: filterVM.definition,
rightImage: UIImage.init(named: "arrow_down")!, isPropertiesChanged: false, isArrowHidden: false)
viewFilterHeader.tag = section
let tap = UITapGestureRecognizer(target: self, action: #selector(hideSection(_:)))
viewFilterHeader.addGestureRecognizer(tap)
viewHeader.addSubview(viewFilterHeader)
viewFilterHeader.snp.makeConstraints { (make) in
make.top.equalTo(7.0)
make.bottom.equalTo(0.0)
make.leading.trailing.equalTo(0)
}
return viewHeader
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 67.0
}
#objc private func hideSection(_ sender: UITapGestureRecognizer? = nil) {
guard let section = sender?.view?.tag else { return }
func indexPathsForSection() -> [IndexPath] {
var indexPaths = [IndexPath]()
for row in 0..<self.filterElementListVM.numberOfRowsInSection(section) {
indexPaths.append(IndexPath(row: row,
section: section))
}
return indexPaths
}
if self.hiddenSections.contains(section) {
self.hiddenSections.remove(section)
self.tableviewFilter.insertRows(at: indexPathsForSection(),
with: .fade)
} else {
self.hiddenSections.insert(section)
self.tableviewFilter.deleteRows(at: indexPathsForSection(),
with: .fade)
}
}
Looks like your configuration works wrong and when you toggle your cell old data applied to your cell. So you need to clear all your data in prepareFroReuse() method inside your UIColelctionViewCell class
More information: https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse
Have a nice day. I created a menu with Tableview, I want to add a logo and label to the top of this menu, just like in the android image. How can I make the menu visual like on Android? In the tableview I created, I show the name and icon of the menu. As with Android, I want to add a logo to the top of the menu.
class MyMenuTableViewController: UITableViewController {
let keychain = KeychainSwift()
private let menuOptionCellId = "Cell"
var selectedMenuItemLogin : Int = 0
var selectedMenuItem : Int = 0
let menuItem : [String] = ["Giriş"]
let menuIteminLogin : [String] = ["MENUITEM1" , "MENUITEM2" , "MENUITEM3","MENUITEM4"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.contentInset = UIEdgeInsets(top: 64.0, left: 0, bottom: 0, right: 0)
tableView.separatorStyle = .singleLine
tableView.backgroundColor = UIColor(hex: 0x464646)
tableView.scrollsToTop = false
clearsSelectionOnViewWillAppear = false
let loginKeychain = keychain.get("LoginSuccess")
tableView.selectRow(at: IndexPath(row: selectedMenuItem, section: 0), animated: false, scrollPosition: .middle)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuIteminLogin.count
}
var imageinLoginCell : [String] = ["gift.png" , "clock.png", "graphic.png","graphic.png"]
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: menuOptionCellId)
if loginKeychain == "2" {
cell!.textLabel?.text = menuIteminLogin[indexPath.row]
cell!.imageView!.image = UIImage(named: imageinLoginCell[indexPath.row])
cell!.textLabel?.font = UIFont(name: "Helvetica-Bold", size: 18)
cell?.textLabel?.textAlignment = .right
if let myImage = UIImage(named: imageinLoginCell[indexPath.row]) {
let tintableImage = myImage.withRenderingMode(.alwaysTemplate)
cell!.imageView!.image = tintableImage
}
cell!.imageView!.tintColor = UIColor.white
if (indexPath.row == 2){
cell!.backgroundColor = UIColor(hex: 0xcf0700)
cell!.textLabel?.font = UIFont(name: "Helvetica-Bold", size: 19)
}
}
return cell!
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50.0
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let loginKeychain = keychain.get("LoginSuccess")
if loginKeychain == nil {
if (indexPath.row == selectedMenuItem) {
return
}
selectedMenuItem = indexPath.row
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main",bundle: nil)
var destViewController : UIViewController
switch (indexPath.row) {
case 0:
destViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginViewNew")
break
default: destViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginViewNew")
break
}
sideMenuController()?.setContentViewController(destViewController)
....
}
}
Use "tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?"
and this function here for Height "tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat"
It will stick on top and the list will scroll underneath of it.
I have a tableview with 3 collapsible sections. users can only select rows in section 3 and when they select it goes green. However, when this section is collapsed all the selections are forgotten and when I re-open the section, usually the first row is always green (though it shouldn't be). Sometimes, other sections end up being green too when they shouldn't - not sure what I've got wrong?
// Number of table sections
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
// Set the number of rows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.expandedSectionHeaderNumber == section) {
// If markscheme, create the markscheme format
if (section == 2)
{
return self.markschemeRows.count
}
else
{
let arrayOfItems = self.sectionItems[section] as! NSArray
return arrayOfItems.count
}
} else {
return 0;
}
}
// Set titles for sections
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if (self.sectionNames.count != 0) {
return self.sectionNames[section] as? String
}
return ""
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44.0;
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat{
return 0;
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
//recast your view as a UITableViewHeaderFooterView
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.backgroundColor = UIColor.darkGray
header.textLabel?.textColor = UIColor.white
if let viewWithTag = self.view.viewWithTag(kHeaderSectionTag + section) {
viewWithTag.removeFromSuperview()
}
let headerFrame = self.view.frame.size
let theImageView = UIImageView(frame: CGRect(x: headerFrame.width - 32, y: 13, width: 18, height: 18));
theImageView.image = UIImage(named: "Chevron-Dn-Wht")
theImageView.tag = kHeaderSectionTag + section
header.addSubview(theImageView)
// make headers touchable
header.tag = section
let headerTapGesture = UITapGestureRecognizer()
headerTapGesture.addTarget(self, action: #selector(CaseViewController.sectionHeaderWasTouched(_:)))
header.addGestureRecognizer(headerTapGesture)
}
// Load the table data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
let section = self.sectionItems[indexPath.section] as! NSArray
cell.textLabel?.textColor = UIColor.black
cell.selectionStyle = .none
//cell.backgroundColor = .white
// Get the data from different arrays depending on the section
if indexPath.section == 2 {
cell.textData?.text = markschemeRows[indexPath.row]
} else {
cell.textData?.text = section[indexPath.row] as! String
}
return cell
}
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if indexPath.section == 0{
if indexPath.row == 0{
return nil
}
}
else if indexPath.section == 1{
if indexPath.row == 0{
return nil
}
}
return indexPath
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
let cell = tableView.cellForRow(at: indexPath)
cell?.backgroundColor = .green
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.cellForRow(at: indexPath)
if (cell?.backgroundColor == .green)
{
cell?.backgroundColor = .white
}
}
// MARK: - Expand / Collapse Methods
#objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) {
let headerView = sender.view as! UITableViewHeaderFooterView
let section = headerView.tag
let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView
if (self.expandedSectionHeaderNumber == -1) {
self.expandedSectionHeaderNumber = section
tableViewExpandSection(section, imageView: eImageView!)
} else {
if (self.expandedSectionHeaderNumber == section) {
tableViewCollapeSection(section, imageView: eImageView!)
} else {
let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
tableViewExpandSection(section, imageView: eImageView!)
}
}
}
func tableViewCollapeSection(_ section: Int, imageView: UIImageView) {
let sectionData = self.sectionItems[section] as! NSArray
self.expandedSectionHeaderNumber = -1;
if (sectionData.count == 0) {
return;
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
// If markscheme, different number needed
if (section == 2)
{
for i in 0 ..< markschemeRows.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
else
{
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
self.tableView!.beginUpdates()
self.tableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.tableView!.endUpdates()
}
}
func tableViewExpandSection(_ section: Int, imageView: UIImageView) {
let sectionData = self.sectionItems[section] as! NSArray
if (sectionData.count == 0) {
self.expandedSectionHeaderNumber = -1;
return;
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
// If markscheme, create the markscheme format
if (section == 2)
{
for i in 0 ..< markschemeRows.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
else
{
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
self.expandedSectionHeaderNumber = section
self.tableView!.beginUpdates()
self.tableView!.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.tableView!.endUpdates()
}
}
The key thing to understand here is that the Cells are Reused when you say
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
dequeueReusableCell basically reuses a previously loaded UITableViewCell and in your case you changed the background color of the cell to green
To get a better understanding of the concept consider reading some articles like this one on Reusing Cells
Changes in Code
What you should do considering the above in mind
var backgroundColors = [UIColor](repeating: UIColor.white, count: 10)
you have to save the state of the colors in a model (ideally you should make a custom struct)
now in cellForRowAt add this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
.
.
cell.backgroundColor = backgroundColors[indexPath.row]
// **EDIT**
let cellShouldBeSelected = backgroundColors[indexPath.row] == .green
if cellShouldBeSelected {
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
}
.
.
return cell
}
And your didSelectRowAt and didDeselectRowAt should update the model
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.backgroundColors[indexPath.row] = .green
tableView.reloadRows(at: [indexPath], with: .none)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if (self.backgroundColors[indexPath.row] == .green) {
self.backgroundColors[indexPath.row] = .white
tableView.reloadRows(at: [indexPath], with: .none)
}
}
On second thought
Solution 2 (Recommended)
From you comments, i see you only need one selected cell at one time, assuming that keeping an array of backgroundColors is just a bad idea.
declare a int for the selected index
// -1 representing nothing is selected in the beginning
var selectedRow = -1
now your cellForRowAt will look like
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
.
.
if indexPath.section == 2, indexPath.row == self.selectedRow {
cell.backgroundColor = .green
} else {
cell.backgroundColor = .white
}
.
.
return cell
}
And your didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 2 {
self.selectedRow = indexPath.row
tableView.reloadSections([2], with: .automatic)
}
}
And now you can remove didDeselectRowAt completely
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arraylist.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50.0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = PopupCellTableViewCell()
cell = (tableView.dequeueReusableCell(withIdentifier: "advnccell", for: indexPath) as? PopupCellTableViewCell)!
cell.bgView = Utilities().viewborder(vw: cell.bgView )
let dict = arraylist[indexPath.row] as! NSDictionary
let cd = dict.value(forKey: "Code") as? String ?? ""
let desc = dict.value(forKey: "Description") as? String ?? ""
cell.tittleLbl.text = cd + " - " + desc
if selectedRows.contains(indexPath)
{
cell.checkBtn.setImage(UIImage(named:"check"), for: .normal)
}
else
{
cell.checkBtn.setImage(UIImage(named:"uncheck"), for: .normal)
}
if (cell.checkBtn.currentImage?.isEqual(UIImage(named: "check")))!
{
UserDefaults.standard.set(cell.tittleLbl.text, forKey: "tittle")
}
cell.btnAction.tag = indexPath.row
cell.btnAction.addTarget(self, action: #selector(checkBoxSelection(_:)), for: .touchUpInside)
return cell
}
// checkbox selection
#objc func checkBoxSelection(_ sender:UIButton)
{
let selectedIndexPath = IndexPath(row: sender.tag, section: 0)
if self.selectedRows.contains(selectedIndexPath)
{
self.selectedRows.remove(at: self.selectedRows.index(of: selectedIndexPath)!)
}
else
{
self.selectedRows.append(selectedIndexPath)
}
self.tableVw.reloadData()
}
At present i am getting only one value, how can i get if i selected multiple check buttons
Fix this portion of your code:
if selectedRows.contains(indexPath)
{
cell.checkBtn.setImage(UIImage(named:"check"), for: .normal)
UserDefaults.standard.set(cell.tittleLbl.text, forKey: "tittle")
}
else
{
cell.checkBtn.setImage(UIImage(named:"uncheck"), for: .normal)
}
I would like that users can choose maximum one voice. And that the checkmark jumps to where you tapt and deselect the other.
It looks like very simple, but I don't see the solution. And I can't find the answer on the internet.
Please can anybody help me?
Thanks advance!
import UIKit
import AVFoundation
class voicesTableViewController: UITableViewController {
fileprivate let synthesizer = AVSpeechSynthesizer()
fileprivate var speechVoices = AVSpeechSynthesisVoice.speechVoices()
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return speechVoices.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
//Name
let voice = speechVoices[indexPath.row]
let voiceLang = voice.language as? String
let theVoice = UserDefaults.standard.object(forKey:"voice") as? String
cell.textLabel?.text = voice.name
// Language
if let language = countryName(countryCode: voice.language) {
cell.detailTextLabel?.text = "\(language)"
}
else {
cell.detailTextLabel?.text = ""
}
cell.detailTextLabel?.textColor = UIColor.gray
// Checkmark
if (theVoice != nil) {
if(theVoice == voiceLang) {
cell.accessoryType = UITableViewCellAccessoryType.checkmark
}
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let voice = speechVoices[indexPath.row]
if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCellAccessoryType.checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.none
}
else
{
//if ((tableView.indexPathsForSelectedRows?.count)! > 1) {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.checkmark
//}
}
UserDefaults.standard.set(voice.language, forKey:"voice")
UserDefaults.standard.synchronize()
tableView.deselectRow(at: indexPath, animated: true)
}
func countryName(countryCode: String) -> String? {
let preferredLanguage = NSLocale.preferredLanguages[0] as String
let current = Locale(identifier: preferredLanguage)
return current.localizedString(forLanguageCode: countryCode) ?? nil
//return current.localizedString(forIdentifier: indentifier) ? nil
}
}
Simple change of function cellForRow:atIndexPathshould work:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
//Name
let voice = speechVoices[indexPath.row]
let voiceLang = voice.language as? String
let theVoice = UserDefaults.standard.object(forKey:"voice") as? String
cell.textLabel?.text = voice.name
// Language
if let language = countryName(countryCode: voice.language) {
cell.detailTextLabel?.text = "\(language)"
}
else {
cell.detailTextLabel?.text = ""
}
cell.detailTextLabel?.textColor = UIColor.gray
// Checkmark
if(theVoice != nil && theVoice == voiceLang) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
return cell
}
UPD#1
But you can use better solution:
1) Add property fileprivate var selectedIndexPath: IndexPath?
2) Change function func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)to next one:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
//Name
let voice = speechVoices[indexPath.row]
let voiceLang = voice.language as? String
let theVoice = UserDefaults.standard.object(forKey:"voice") as? String
cell.textLabel?.text = voice.name
// Language
if let language = countryName(countryCode: voice.language) {
cell.detailTextLabel?.text = "\(language)"
}
else {
cell.detailTextLabel?.text = ""
}
cell.detailTextLabel?.textColor = UIColor.gray
// Checkmark
cell.accessoryType = self.selectedIndexPath == indexPath ? .checkmark : .none
return cell
}
3) And then in func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) you can do next:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let voice = speechVoices[indexPath.row]
self.selectedIndexPath = indexPath
UserDefaults.standard.set(voice.language, forKey:"voice")
UserDefaults.standard.synchronize()
tableView.deselectRow(at: indexPath, animated: true)
tableView.reloadRows(at: [indexPath], with: .automatic)
}