I have my default selected cell in my table view. I want to change this selected language when tapped but could not able to do so. I am getting an error at '$0' line:
var languageViewModel = LanguageViewModel()
var languageTitles: [LanguageModel] = []
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = languageTitles[indexPath.row]
var value = item.isSelected
// Edit isSelected property and refresh table
languageTitles.forEach { $0.isSelected = false }
item.isSelected = !value
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return languageCell(indexPath: indexPath)
}
private func languageCell(indexPath: IndexPath) -> LanguageTableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: LanguageTableViewCell.identifier, for: indexPath) as! LanguageTableViewCell
let item = languageTitles[indexPath.row]
if item.isSelected {
cell.setupSelected(item)
} else {
cell.setup(item)
}
return cell
}
struct LanguageModel {
let language: Language
var isSelected: Bool = false
}
class LanguageViewModel {
var locales: [Language] = [.tr, .eng, .az] //.ar
var currentLanguage = UserDefaultsUtil.getDeviceLanguage()
var languages: [LanguageModel] = []
func getLanguageTitles() {
languages = [
LanguageModel(language: .tr, isSelected: currentLanguage == locales[0].code),
LanguageModel(language: .eng, isSelected: currentLanguage == locales[1].code),
LanguageModel(language: .az, isSelected: currentLanguage == locales[2].code)
]
}
}
I can not tap on another cell when I want to change the language. It is always the selected one from the view model
if I change didselectrowat to
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = languageTitles[indexPath.row]
var value = item.isSelected
// Edit isSelected property and refresh table
for languageTitle in languageTitles {
languageTitle.isSelected = false
}
item.isSelected = !value
tableView.reloadData()
}
Cannot assign to property: 'languageTitle' is a 'let' constant
CodePudding user response:
Replace this:
languageTitles.forEach { $0.isSelected = false }
With:
for index in languageTitles.indices {
languageTitles[index].isSelected = false
}
forEach
has various subtle and surprising behaviors. It is generally best to use a for-in
instead. But the key issue is that LanguageModel
is a struct and has value semantics. When you assign it to a variable (i.e. $0, or the variable in a for-in loop), a copy is made. If you make changes to the copy, they don't modify the array. (By default they're constants, so you can't modify them anyway.) Assigning through the subscript operator, however, does what you expect.
CodePudding user response:
It can afford such a structure like :
languageTitles.indices.forEach { languageTitles[$0].isSelected = false }