Solución:
Cree una estructura para los datos del modelo con una propiedad Bool. Puede modificar esta propiedad mediante la selección de celda.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
var allCharacters:[Character] = []
override func viewDidLoad()
super.viewDidLoad()
allCharacters = [Character(name: "All"),Character(name: "Luke Skywalker"),Character(name: "Leia Organa"),Character(name: "Advik Shah"),Character(name: "Aarav Modi")]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return allCharacters.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil
cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
cell?.textLabel?.text = allCharacters[indexPath.row].name
if allCharacters[indexPath.row].isSelected
cell?.accessoryType = .checkmark
else
cell?.accessoryType = .none
cell?.selectionStyle = .none
return cell!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
if indexPath.row == 0
allCharacters[indexPath.row].isSelected = !allCharacters[indexPath.row].isSelected
for index in allCharacters.indices
allCharacters[index].isSelected = allCharacters[indexPath.row].isSelected
else
allCharacters[indexPath.row].isSelected = !allCharacters[indexPath.row].isSelected
if allCharacters.dropFirst().filter( $0.isSelected ).count == allCharacters.dropFirst().count
allCharacters[0].isSelected = true
else
allCharacters[0].isSelected = false
tableView.reloadData()
struct Character
var name:String
// var otherDetails
var isSelected:Bool! = false
init(name:String)
self.name = name
Creación de objetos Array of Struct a partir de array de diccionario
let SubjectArray = json["students"] as! [[String:Any]]
allCharacters = SubjectArray.map( Character(name: $0["studentName"] as! String) )
allCharacters.insert(Character(name:"All"), at: 0)
Me gusta la sugerencia de @ Pranil de usar una sección separada para la fila “Todos”, así que la he robado.
Puedes usar un NSMutableIndexSet
para rastrear las filas seleccionadas. Esto es más simple que tener que crear una nueva estructura o array de booleanos o algo así. Lo único que debe tener en cuenta es que si su vista de tabla permite el reordenamiento de filas, entonces el conjunto de índices debe ajustarse en consecuencia.
Aquí está mi implementación. El estado “todos” está determinado por el número de filas seleccionadas que es igual al número de filas en la fuente de datos. array.
Acabo de usar accesorios simples de vista de tabla para las marcas de verificación, pero estoy seguro de que puede ver cómo adoptar su enfoque basado en imágenes en cellForRow(at:)
importar UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
@IBOutlet weak var tableview: UITableView!
let names: [String]? = ["Luke Skywalker","Leia Organa","Advik Shah","Aarav Modi"]
var selectedRows = NSMutableIndexSet()
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func numberOfSections(in tableView: UITableView) -> Int
return 2
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
guard let names = self.names else
return 0
return 0 == section ? 1 : names.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
var text: String
var accessory = UITableViewCellAccessoryType.none
if 0 == indexPath.section
text = "All"
if self.selectedRows.count == self.names!.count
accessory = .checkmark
else
text = names![indexPath.row]
if selectedRows.contains(indexPath.row)
accessory = .checkmark
cell.textLabel!.text = text
cell.accessoryType = accessory
return cell
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
if indexPath.section == 0
if self.selectedRows.count == self.names!.count
self.selectedRows = NSMutableIndexSet()
else
self.selectedRows = NSMutableIndexSet(indexesIn: NSRange(location: 0, length: self.names!.count))
tableView.reloadData()
else
self.selectedRows.contains(indexPath.row) ? self.selectedRows.remove(indexPath.row) : self.selectedRows.add(indexPath.row)
let rows = [IndexPath(row: 0, section: 0), indexPath]
tableView.reloadRows(at: rows, with: .none)
return nil
Creo que está utilizando solo una sección en la vista de tabla. Le sugiero que use dos secciones en la vista de tabla, de modo que la primera sección contendrá solo una fila (Seleccionar todo) y la segunda sección contendrá otras opciones. Cuando hace clic en Seleccionar todo, es decir, en la primera fila de la primera sección, puede hacer que todas las filas de la segunda sección estén seleccionadas mientras vuelve a cargar la vista de tabla.
// MARK: - struct for cell item
struct CellItem
var name : String
var isSelected:Bool! = false
init(name: String)
self.name = name
class ViewController: UITableViewController
@IBOutlet var viewTable: UITableView!
// Declare a boolean varaible to toggle the checkbox in the first section of table view
var isSelectAllSelected : Bool = false
var cellData: [CellItem] = []
override func viewDidLoad()
super.viewDidLoad()
cellData = [CellItem(name: "Luke Skywalker"),CellItem(name: "Leia Organa"),CellItem(name: "Advik Shah"),CellItem(name: "Aarav Modi")]
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int
return 2
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
if section == 0
return 1
else
return cellData.count
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
return 0
// MARK: - Table view delegates
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 60
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = TableCell()
cell.selectionStyle = .none
if indexPath.section == 0
cell.textLabel?.text = "Select All"
if isSelectAllSelected
cell.accessoryType = .checkmark
else
cell.accessoryType = .none
else
cell.textLabel?.text = cellData[indexPath.row].name
if cellData[indexPath.row].isSelected
cell.accessoryType = .checkmark
else
cell.accessoryType = .none
return cell
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
if indexPath.section == 0
cellData[indexPath.row].isSelected = !cellData[indexPath.row].isSelected
isSelectAllSelected = cellData[indexPath.row].isSelected
for index in cellData.indices
cellData[index].isSelected = cellData[indexPath.row].isSelected
else
cellData[indexPath.row].isSelected = !cellData[indexPath.row].isSelected
if cellData.filter( $0.isSelected ).count == cellData.count
isSelectAllSelected = true
else
isSelectAllSelected = false
viewTable.reloadData()
Finalizando este artículo puedes encontrar las ilustraciones de otros gestores de proyectos, tú incluso tienes la habilidad insertar el tuyo si dominas el tema.