Programmatically Select All Cells in Tableview So Next Time They Are Pressed They Call Diddeselect

Selecting every row in TableView including off-screen rows

You don't.

You can't select all cells because they're being reused, which means only enough cells exist.

When the "Acknowledge" button is pressed, you can get the data from your datasource, the one you're consuming to create your UITableView.


Note: If there is a state change when that button is pressed, you should iterate through your datasource and update your objects. And then you .reloadData().


Updates based on your question update, this is how you iterate through your datasource.

        var dataClassArr = [DataClass]()

var result = [String]()

dataClassArr.append(DataClass(id: "1"))
dataClassArr.append(DataClass(id: "42")) // just for example, you should remove those.

for element in dataClassArr {
result.append(element.id)
}

print(result) // ["1", "42"] -> based on example values.

iOS having issues with UITableView programmatically selecting multiple cells and displaying a check

Override the setSelected method in the custom tableview cell class,

and use tableview.selectRow(at:) function to select cells.

Use tableView.indexPathsForSelectedRows to get selected indexPaths in the table.

Here is a good implementation.
https://github.com/yonat/SelectionList

Reply To New Issue:
Please follow the steps.

  1. viewDidLoad or viewWillAppear method

        var itemsToBeSelected: [String]?
    var listItems: [String]?

    ....
    override func viewDidLoad() {
    super.viewDidLoad()
    if let selected = self.itemsToBeSelected, let listItems = self.listItems {
    selected.forEach { (item) in
    if let index = listItems.index(of: item) {
    let indexPath = IndexPath(item: index, section: 0)
    self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
    }
    }
    }

    self.itemsToBeSelected means they need to be selected by default in the list when the view controller appears. it's just an array of String in the above example.

  2. cellForRowAt method

    No need to call cell.isSelected = true/false or cell.isHighlighted = true/false

    if the cell is a custom cell, you can just apply the content to the cell only. and in the custom cell class, just override setSelected method.

    class ExpansionBayCell {
    ....
    override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    self.checkBox.isChecked = self.isSelected
    }
    }
  3. when it's time to get all selected values and close the view controller

    func btnDonePressed() {        
    guard let indexPaths = tableView.indexPathsForSelectedRows else {
    btnBackPressed()
    return
    }

    let items = indexPaths.map { self.listItems[$0.row] }
    completion(items)
    btnBackPressed()
    }

How to Programmatically Pre-select Cells in a Multi-select UITableView in iOS

You should manage it entirely using your data model.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)

// Assumption: item is a class, so changes are reflected in array as expected
let item = items[indexPath.row]
item.isSelected.toggle()

cell!.accessoryType = item.isSelected ? .checkmark : .none
}

This way there's always one source of truth, your data model. Your tableView instance should not need to remember anything for you, it's driven by the data you provide.

If you go this way, you don't need to implement didDeselect delegate method OR set allowsMultipleSelection to true.

-didSelectRowAtIndexPath: not being called

It sounds like perhaps the class is not the UITableViewDelegate for that table view, though UITableViewController is supposed to set that automatically.

Any chance you reset the delegate to some other class?

Manually call didSelectRowatIndexPath

You need to pass a valid argument, if you haven't declared indexPath in the calling scope then you'll get that error. Try:

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:ROW_YOU_WANT_TO_SELECT inSection:SECTION_YOU_WANT_TO_SELECT]
[self tableView:playListTbl didSelectRowAtIndexPath:indexPath];

Where ROW_YOU_WANT... are to be replaced with the row and section you wish to select.

However, you really shouldn't ever call this directly. Extract the work being done inside tableView:didSelectRowAtIndexPath: into separate methods and call those directly.

To address the updated question, you need to use the indexPathsForSelectedRows method on UITableView. Imagine you were populating the table cell text from an array of arrays of strings, something like this:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tv dequeue...];
NSArray *rowsForSection = self.sectionsArray[indexPath.section];
NSString *textForRow = rowsForSection[indexPath.row];
cell.textLabel.text = textForRow;
return cell;
}

Then, to get all the selected text, you'd want to do something like:

NSArray *selectedIndexPaths = [self.tableView indexPathsForSelectedRows];
NSMutableArray *selectedTexts = [NSMutableArray array];
for (NSIndexPath *indexPath in selectedIndexPaths) {
NSArray *section = self.sectionsArray[indexPath.section];
NSString *text = section[indexPath.row];
[selectedTexts addObject:text];
}

selectedTexts would at that point contain all selected information. Hopefully that example makes sense.

How to select item in collectionview programmatically?

You can simply use this after [self.collectionView reloadData]

[self.collectionView 
selectItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]
animated:YES
scrollPosition:UICollectionViewScrollPositionCenteredVertically];

where index is the index number for the selected student.

Using a button to deselect cells in a collectionview

It is a bad idea to store selected index paths, as these are coupled to the collection view. If you store the selected items then you can always determine the appropriate index path, using the item's index in the array. You can also determine an item quickly from a given index path.

In the code below I have used the type Item for your underlying item, but it could be String or Int or any object type. If you use your own class or struct, ensure you make it conform to Equatable and Hashable.

var allItems:[Item]
var selectedItems[Item]

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == allItemsCV {
let item = allItems[IndexPath.row]
if let itemIndex = selectedItems.index(of:item) {
selectedItems.remove(at:itemIndex)
selectedItemsCV.deleteItems(at: [IndexPath(item: itemIndex, section:0)])
} else {
selectedItems.insert(item, at: 0)
selectedItemsCV.insertItems(at: [IndexPath(item: 0, section:0)])
}
allItemsCV.deselectItem(at: indexPath, animated: true)
// cell for item at indexPath needs to render the selected/deselected
state correctly based on the item being in the selectedItems array

allItemsCV.reloadItems(at: [indexPath])

}
}

@IBAction func removeButtonPressed(_ sender: UIButton) {
//...
if let selectedItemPaths = selectedItemCV.indexPathsForSelectedItems {
var allItemIndexPaths = [IndexPath]()
var tempSelectedItems = Array(selectedItems) // Need to use a temporary copy otherwise the element indexes will change
for itemPath in selectedItemPaths {
let removeItem = selectedItems[itemPath.item]
if let removeIndex = tempSelectedItems.index(of: removeItem) {
tempSelectedItems.remove(at: removeItem)
}
if let allItemsIndex = allItems.index(of: removeItem) {
allItemIndexPaths.append(IndexPath(item: allItemsIndex, section: 0))
}
}
selectedItems = tempSelectedItems // Selected items array without the removed items
selectedItemsCV.deleteItems(at:selectedItemPaths)
allItemsCV.reloadItems(at: allItemIndexPaths) // Reload to update the selected status
}
}


Related Topics



Leave a reply



Submit