如何使用一个 UIButton 从 UITableView 中选择和取消选择所有复选标记?

Posted

技术标签:

【中文标题】如何使用一个 UIButton 从 UITableView 中选择和取消选择所有复选标记?【英文标题】:How to select and deselect all the checkmarks from a UITableView with one UIButton? 【发布时间】:2015-12-07 20:47:09 【问题描述】:

如何一键选择和取消选择此 UITableView 中的所有单元格?

我在使用此按钮时遇到问题。所以,我的想法是,当我点击它时,UITableView 中的所有单元格都有一个复选标记(选择),当我再次单击它时,所有单元格都没有复选标记(取消选择)。

我已经实现了 UIButton 在单击后更改名称(从“全选”到“取消全选”,反之亦然)。

这些是我写的:

let locationItems:[String] = ["China", "United States", "South Africa", "Spain", "Australia", "Brazil", "Colombia", "Nigeria", "India"]
var selectedItemsIndex:Int?
var selectIndicator = true

@IBOutlet var tableViewWithOptions: UITableView!
@IBOutlet var selectAllLabel: UIButton!

@IBAction func selectAllButton(sender: AnyObject) 
    if (selectIndicator == true) 

        if selectAllLabel.titleLabel?.text == "Select all" 
            selectAllLabel.setTitle("Deselect all", forState: UIControlState.Normal)
        
        selectIndicator = false
     else 

        if selectAllLabel.titleLabel?.text == "Deselect all" 
            selectAllLabel.setTitle("Select all", forState: UIControlState.Normal)
        
        selectIndicator = true
    
    tableViewWithOptions.reloadData()


    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
        if let index = selectedItemsIndex 
            let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0))
            cell?.accessoryType = .None
        
        let cell = tableView.cellForRowAtIndexPath(indexPath)
        cell?.accessoryType = .Checkmark
    

请告诉我。 谢谢!

【问题讨论】:

您需要首先让您的数据模型跟踪当前选择的行。 您无法在单元格中跟踪选择状态(使用附件类型),您需要一些其他变量。我推荐一个 NSMutableIndexSet。选择一个单元格意味着将行添加到集合中,取消选择意味着将其删除。全选是通过 addIndexesInRange 完成的,取消全选只是为了清除索引集 【参考方案1】:

将您的 UITableViewCells 视为只是在数据源中显示您的数据,更容易认为它们只能呈现信息,而要呈现新信息,您必须更新数据源并重新加载表格视图。

我看到您的数据源是locationItems,它是一个字符串数组。如果将项目的类型更改为 String 和 Bool 类型的元组,则可以将位置名称和 bool 分配给数组中的单个元素,bool 表示选中(true)或未选中(false)

所以把locationItems改成:

//out data source, contains an array of Tuples containing a string and a bool
let locationItems:[(String, Bool)] = [("China", true), ("United States",false), ("South Africa", false), ("Spain", true), ("Australia", true), ("Brazil",     false), ("Colombia", true), ("Nigeria", true), ("India", true)]

正如你在上面看到的,数组中的每个元素都包含一个String和一个Bool,这个bool表示一个国家是否被选中。

所以要“检查”所有单元格,我们将更改数据源中的值并重新加载 tableView。这将导致再次调用cellForRow,然后单元格将拥有来自我们更新的数据源的新数据。

@IBAction func selectAllButton(sender: AnyObject) 
    //loop through our data source and change the bool in each element to true
    //to indicate that all locations are checked
    for item in locationItems 
        //access second item in the tuple which is our bool and set it's value to true
        item.1 = true
    
    tableView.reloadData()

因此,您如何执行此操作的一般要点是您编辑 tableView 从中获取数据的数据源,而不是直接更改单元格。

【讨论】:

【参考方案2】:

正如其他人指出的那样,您必须为您的位置及其选择状态维护一个数据模型,以便轻松处理您的场景。您可以为您的位置信息定义一个简单的模型。在 ViewController 类中定义此模型 struct

位置模型

struct Location 
    var name: String
    var selected: Bool

    init(_ name: String, _ selected:Bool) 
        self.name = name
        self.selected = selected
    

现在您的模型已定义,您需要加载数据源和属性的初始值。 [注意:你也可以使用帮助类来填充你的数据源。]

var selectionStateIndicator = false
var locationItems: [Location] = 
    var _locations = [Location]()
    var locationNames = ["China", "United States", "South Africa", "Spain", "Australia", "Brazil", "Colombia", "Nigeria", "India"]

    for location in locationNames 
        _locations.append(Location(location, false))
    

    return _locations
()

更新您的cellForRowAtIndexPath 方法以使用新的数据模型来显示数据。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)

    cell.textLabel?.text = self.locationItems[indexPath.row].name
    cell.accessoryType = self.locationItems[indexPath.row].selected ? .Checkmark : .None

    return cell

更新您的selectAllButton 操作以使用新模型对象并更新每一行的选择状态。

@IBAction func selectAllButton(sender: AnyObject) 
    selectionStateIndicator = !selectionStateIndicator

    for var location in locationItems 
        location.selected = selectionStateIndicator
    

    tableViewWithOptions.reloadData()

更新您的didSelectRowAtIndexPath 方法,以便每当有单独的行选择时,您都会相应地更新该行。

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 

    let cell = tableView.cellForRowAtIndexPath(indexPath)
    locationItems[indexPath.row].selected = !locationItems[indexPath.row].selected

    if !locationItems[indexPath.row].selected 
        cell?.accessoryType = .None
     else 
        cell?.accessoryType = .Checkmark
    

【讨论】:

以上是关于如何使用一个 UIButton 从 UITableView 中选择和取消选择所有复选标记?的主要内容,如果未能解决你的问题,请参考以下文章

表内的 UIButton 未触发

如何在 UITableView Cell 中以编程方式创建 n 个 UIButton?

Swift uiview 在 uitable 之上

UItableView Cell上的UIbutton不可点击

UIButton 在 iOS 7 中无法正常工作

如何在 swift 3 中为 UITable 视图提供单元格缩进级别?