【问题标题】:UISwitch in tableview row表视图行中的 UISwitch
【发布时间】:2018-10-06 12:34:15
【问题描述】:

在下面的代码中,我用一些数据填充我的表。开关已关闭,它们不必关闭。在情节提要中,我将其定义为 On。

单元格:

var switchHandler: ((Bool)->Void)?

@IBAction func switchChanged(_ sender: UISwitch) {
    self.switchHandler?(sender.isOn)
}

视图控制器:

var selectedCells = Set<IndexPath>()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "SmsCell") as? SmsTableViewCell

    cell?.PhonNumberLbl.text = data![indexPath.section].contacts[indexPath.row]?.phoneNumber
    cell?.NameLbl.text = data![indexPath.section].contacts[indexPath.row]?.name
    cell?.selectedTF.isOn = (data![indexPath.section].contacts[indexPath.row]?.selected)!

    cell?.selectedTF.isOn = self.selectedCells.contains(indexPath)
    cell?.switchHandler = { (switchState) in
        if switchState {
            self.selectedCells.insert(indexPath)
        } else {
            self.selectedCells.remove(indexPath)
        }
    }

    return cell!
}

型号:

typealias smsModelList = [SmsModel]

struct SmsModel:Codable {
    var unitNo:Int?
    var unitPlaque:String?
    var billText:String?
    var contacts:[ContactsModel?]
}

typealias contactlistmodel = [ContactsModel]

struct ContactsModel:Codable
{
    var id :Int?
    var selected :Bool?
    var phoneNumber : String?
    var name : String?
}

有人看到关闭开关的问题吗?

【问题讨论】:

  • 嗨,杰克。在UIViewController 的哪里找到代码?您的代码有些不完整,因此很难猜测您的上下文。具体来说,我不确定indexPath 来自哪里。所以我不确定这段代码存在于哪个方法中,是委托方法实现还是自定义方法。能具体说明一下吗?
  • 您好,欢迎您。请编辑您的问题以在上下文中显示代码;这些行包含哪些功能?您正在根据模型中的一些数据和您选择的集合设置开启状态;您可能应该只使用其中之一

标签: ios swift uitableview uiswitch


【解决方案1】:

首先,当您强制解开单元格时,请在 dequeue 行中执行此操作以避免不必要的问号数量,并使用 API 返回一个非可选单元格

let cell = tableView.dequeueReusableCell(withIdentifier: "SmsCell", for: indexPath) as! SmsTableViewCell

要解决您的问题,请直接更新 ContactsModel 结构的 selected 属性并忘记额外的 selectedCells 数组。进一步声明 - 至少 - selected 是非可选的,实际上没有 maybe 状态。并且还将所有数据源数组(data/contacts)声明为非可选,默认情况下,仅当特定 indexPath 处有项目时才会调用 cellForRow

struct ContactsModel : Codable {
   ...
   var selected : Bool
   ...
}

...

let cell = tableView.dequeueReusableCell(withIdentifier: "SmsCell", for: IndexPath) as! SmsTableViewCell
let contact = data[indexPath.section].contacts[indexPath.row]
cell.PhonNumberLbl.text = contact.phoneNumber
cell.NameLbl.text = contact.name
cell.selectedTF.isOn = contact.selected

cell.switchHandler = { [unowned self] switchState in
    // as the structs are value types you have to specify the full reference to the data source array
    self.data[indexPath.section].contacts[indexPath.row].selected = switchState
}

在这种情况下考虑使用类而不是结构,然后你可以缩短闭包

cell.switchHandler = { switchState in
    contact.selected = switchState
}

【讨论】:

  • 您好,先生,很抱歉我迟到了,无法查看您对我的问题的回答。我有点忙!有没有办法代替这样做,例如,我可以在导航控制器上添加一个开关,用那个按钮打开或关闭所有功能?
  • 你用而不是这样做是什么意思?
  • 此方法中,用户逐行打开或关闭开关
  • 当然可以,更改所有selected属性并重新加载表格视图。
  • 你能解释一下吗
【解决方案2】:

两个都用

cell?.selectedTF.isOn = (data![indexPath.section].contacts[indexPath.row]?.selected)! 
cell?.selectedTF.isOn = self.selectedCells.contains(indexPath)

所以isOn开关的属性是从两侧控制的,所以你必须决定哪一行应该被注释,另外不要依赖故事板原型单元设置,因为单元重用它会被改变,如果你想让它们默认都打开,那么更改 var selectedCells 以包含所有可能的 indexPaths 并注释另一个

【讨论】:

  • 如果我删除 cell?.selectedTF.isOn = self.selectedCells.contains(indexPath) ,它不会为我创建能够从 api 调用方法的属性,所以,我必须删除单元格?.selectedTF.isOn = (data![indexPath.section].contacts[indexPath.row]?.selected)!
  • 你是什么意思:“更改 var selectedCells 以包含所有可能的 indexPaths 并评论另一个”
  • 我的意思是创建一个 for 循环并根据部分和行数插入所有可能的 indexPaths,所以当询问包含在 cellForRowAt 内时,它会返回 true,所以所有都将打开,并评论这一行cell?.selectedTF.isOn = (data![indexPath.section].contacts[indexPath.row]?.selected)!
  • 我通过 for 循环获得状态并将它们放入 cell?.selectedTF.isOn = (data![indexPath.section].contacts[indexPath.row]?.selected)!跨度>
  • 然后删除另一个 Set 并操作您评论的数组 contacts
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多