UITableViewController changing one reusable cell affects other cells - ios

I have a very simple UITableViewController subclass designed to show users the characters in the alphabet in cells. When the user presses on a cell, it is to set its accessory type to a checkmark.
#import "MTGTableViewController.h"
#interface MTGTableViewController ()
#property (nonatomic, strong) NSArray *data;
#end
#implementation MTGTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_data = #[#"A", #"B", #"C", #"D", #"E", #"F", #"G", #"H", #"I", #"J", #"K", #"L", #"M", #"N", #"O", #"P", #"Q", #"R", #"S", #"T", #"U", #"V", #"W", #"X", #"Y", #"Z"];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"reuseIdentifier" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = _data[indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
#end
The table view works fine. I have my reuseIdentifier property set in the storyboard on my prototype cells, and it all looks good before I start selecting cells.
The problem: When I select any cell, say the "A" cell, other not-yet-visible cells are also given checkmarks when i scroll down to them. Even worse, when I scroll up and down, sometimes the checkmark on cell "A" is removed and given to cell "B".

This is because of the way table views reuse cells. You need to make sure to clear the accessory item after you call dequeueReusableCellWithIdentifier. eg:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"reuseIdentifier" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = _data[indexPath.row];
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
Although--you're going to have a different problem after you make this change. The cell is going to "forget" that it is selected because of this code. So you'll need to actually change that line where the accessoryType is set to check and see if the cell is selected or not.

I had this problem a little while ago as well, you need to add another array that keeps track of the which cell are marked. Just make an array of NSIndexPaths that are the ones marked.
Sort of like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([arrayOfMarked containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}

For Swift 3:
A simplified version I discovered was to use swifts ".indexPathsForSelectedRows" just within the "cellForRowAt" function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
//To keep from reusing checkmark in reusableCell
if let selectedIndexPaths = tableView.indexPathsForSelectedRows {
if selectedIndexPaths.contains(indexPath) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}
cell.contactsOutlet.text = namesOrganized[indexPath.section].names[indexPath.row]
return cell
}
Then in didSelect and didDeselect:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryType = UITableViewCellAccessoryType.checkmark
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryType = UITableViewCellAccessoryType.none
}

on didselectRowAtIndex path, append the index path into an array of indexpath
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if selectedIndexPaths.contains(indexPath) {
let indexOfIndexPath = selectedIndexPaths.indexOf(indexPath)!
selectedIndexPaths.removeAtIndex(indexOfIndexPath)
} else {
selectedIndexPaths += [indexPath]
}
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
and then on the cellForRowAtIndexPath use the selectedIndexpaths Array to check if the cell is selected or not
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let mycell = tableView.dequeueReusableCellWithIdentifier("yourCell", forIndexPath: indexPath) as! YourCustomCell
.
.
.
if selectedIndexPaths.contains(indexPath){
// do what you want to do if the cell is selected
} else {
// do what you want to do if the cell is not selected
}

Related

How to avoid getting highlighted two cells in a tableview?

Hi in my application i am using one tableview and each cell contains one collection view. When i select one cell in tableview that cell should highlight in light gray and previous should change to black this i am doing as like below.
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
collectionView.backgroundColor=[UIColor clearColor];
collectionViewTagValue=collectionView.tag;
nextFocusedIndex=indexPath;
selectedCollectionCellTag=collectionView.tag;
// Get previously selected collectionview tag value(Because we have many collectionvies in table)
NSIndexPath *previousPath=[NSIndexPath indexPathForRow:self->appdelegateObject.guideSelectionTag inSection:0];
// Get Tableview cell based on tag value - that tag value will be a tableview row number
DetailTableViewCell *cell = (DetailTableViewCell*)[self->guideDetailsTable cellForRowAtIndexPath:previousPath];
// Get indexpath of a selected cell in collection view
NSIndexPath *previouslySelectedCell=[NSIndexPath indexPathForRow:self->appdelegateObject.guideSelectionIndex inSection:0];
// Get collectionview cell based on indexpath value
MainCollectionViewCell *previousCell = (MainCollectionViewCell*)[cell.collection cellForItemAtIndexPath:previouslySelectedCell];
// Change celllabel background color to normal not highlight
previousCell.cellLable.backgroundColor=[UIColor colorWithRed:0.073 green:0.073 blue:0.073 alpha:1.0];
MainCollectionViewCell *currentCell = (MainCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
currentCell.cellLable.backgroundColor=[UIColor lightGrayColor];
}
using above code sometimes both previous and current cells are getting highlighted with light gray.Even if i did this change in dispatch_main_queue also same behaviour i observed. Can any one please suggest best approach for this feature.
Note : For first cell selection i am getting collectionview.tag as -1.
Implemented following method to fix your issue:
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let yourCell = tableView.cellForRow(at: indexPath)
yourCell?.backgroundColor = UIColor.black
}
This code in Swift, you need to convert it to Objective-C.
This method call for previous cell which you have selected, it being deselect.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.contentView.backgroundColor = UIColor.red
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.contentView.backgroundColor = UIColor.lightGray
}
//add condition in tableView delegate in didselect or diddeSelect, check index.section..
//for selected cell
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = (UITableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
// check indexPath.Section here
if (!indexPath.section) == 0{
cell.contentView.backgroundColor = [UIColor yellowColor];
}
}
//for other cells
-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
// check indexPath.Section here
if (!indexPath.section) == 0{
cell.contentView.backgroundColor = [UIColor whiteColor];
}
}
// hope its works for you!

How do I embed a UITableView in a UIView?

I have a UIView in a custom view that I built using xib. I need to display a UITableView in the said view. At first I thought about placing a container and embedding a UITableViewController in it. Turns out I cannot place containers in a xib file, or atleast there's no way of doing it from the IB as it doesn't show up in views section at the lower right.
I can create a UITableView programmatically and add it as a subview of the view. It shows up as expected but I cannot seem to be able to add cells in it. I also tried creating a well behaving UITableViewController in association with a storyboard view, instantiate that controller as follows:
let storyboard = (UIStoryboard(name: "Main", bundle: nil))
let vc = storyboard.instantiateViewControllerWithIdentifier("tableViewController") as! TestTableViewController
and then tried accessing the UITableView's outlet which was nil. Then I read somewhere that I should do a vc.loadView() because as the name suggests, it loads the view and my IBOutlet would not be nil. This worked. The outlet was on longer nil. But, when I add the table in the container view as a subview, it still shows no cells. There are only separator lines but no content. I've run out of ideas!
EDIT
I do not have any UITableViewCell implementations as the tables are static.
Good approach is to use UITableview inside your custom view:
if you are adding tableview programmatically then register your cell using Nib or UITableview subclass like
tableView.registerNib(UINib(nibName: "UITableViewCellSubclass", bundle: nil), forCellReuseIdentifier: "UITableViewCellSubclass")
for if you are creating UITableviewCell using Xib.
tableView.registerClass(UITableViewCellSubclass.self, forCellReuseIdentifier: "UITableViewCellSubclass") // using code.
tableView.delegate = self
tableView.dataSource = self
and then use 2 required delegates.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return tableView.dequeueReusableCellWithIdentifier("UITableViewCellSubclass", forIndexPath: indexPath) as! UITableViewCellSubclass
}
hope i answered your question.
Objective c
You need delegates in your viewcontroller, if you have a viewcontroller, put delegate of table :
UIViewController
UITableViewDelegate
UITableViewDataSource
And you can use your functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; //count of section
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [catagorry count]; //count number of row from counting array hear cataGorry is An Array
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the provided setImageWithURL: method to load the web image
// Ensure you use a placeholder image otherwise cells will be initialized with no image
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://example.com/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder"]];
cell.textLabel.text = #"My Text";
return cell;
}
Swift :
delegate:
UIViewController
UITableViewDataSource
UITableViewDelegate
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
Swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath)
let row = indexPath.row
cell.textLabel?.text = swiftBlogs[row]
return cell
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath)
let row = indexPath.row
cell.textLabel?.text = swiftBlogs[row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return swiftBlogs.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
Look more More inf

How do I hide the multi-select edit gui for certain cells in UITableView?

I am using UITableView, setting editing true, and using these options in interface builder:
This shows a nice selection UI whose style I can modify and events I can react to:
I want to turn this off, but only for certain cells. I've seen this and many similar questions, but they refer to a different type of selection in UITableView. UITableViewCellSelectionStyle.None and willSelectRowAtIndexPath do not allow me to block this type of selection.
Did you try to implement
func tableView(_ tableView: UITableView,
canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
in your delegate ?
I believe it will allow you to obtain the results you are trying to achieve.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if(indexPath.row == index of cell you don't want the selection for)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [a objectAtIndex:indexPath.row];
return cell;
}
For example:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *a = #[#"md",#"dh",#"kkd",#"dkkls"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if(indexPath.row == 2)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [a objectAtIndex:indexPath.row];
return cell;
}
it won't show selection for "kkd" in your tableview

iOS: how to dequeue reusable 'default' cells without actually having a cell in storyboard

I have several tables the default cells such as the one with title, or the one with icon on the left and title on the right.
I don't want to add those cells in storyboard and assign identifier to them, is it possible to do that?
It has to be reusable, I know how to alloc new non-reusable cells
I have tried the answers below,
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:MyCellIdentifier];
should be correct, but it's very tedious and easily forget
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
The above maybe better since it puts all the code at one place, but when I try dequeueReusableCellWithIdentifier:forIndexPath: (with indexPath) it crashes.
Why does dequeueReusableCellWithIdentifier:forIndexPath crashes while dequeueReusableCellWithIdentifier does not?
if i don't pass in indexPath, is the cell reusable
if it is reusable, then whats the use of dequeueReusableCellWithIdentifier:forIndexPath?
If you don't have any prototype cell in your storyboard, you can use the dequeueReusableCellWithIdentifier: api to create classic cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
swift:
var cell : UITableViewCell!
cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier)
}
Swift 3.0
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {
return UITableViewCell(style: .default, reuseIdentifier: "cell")
}
return cell
}()
cell.textLabel?.text = anyArray[indexPath.row]
return cell
}
It is good, because give cell unwrapped.
You can dequeue a UITableViewCell without having a prototype cell in your storyboard. You need to register the cell with your table for a specific identifier (string). You would do this like so:
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:MyCellIdentifier];
You could do this in viewDidLoad, maybe.
Then, you can dequeue a cell using that identifier in your cellForRowAtIndexPath method as usual.
Edit:
Where MyCellIdentifier is a constant you have defined somewhere, of course.
You need to try to dequeue the cell, and if you get nil than create it. In the cell xib file define it's identifier.
Set the cell identifier in the nib file:
Get a reusable cell or make a new one:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"myCell";
MyCell *cell = (MyCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSArray *t = [[NSBundle mainBundle] loadNibNamed:#"myCellXibFileName" owner:nil options:nil];
for (id currentObject in t)
{
if ([currentObject isKindOfClass:[MyCell class]])
{
cell = (MyCell *)currentObject;
break;
}
}
}
// Do whatever you want with the cell....
return cell;
}
Open components library, drag a UITableViewCell into your TableView storyboard, and select this cell to open the identity inspector, then select the default style you want and set the cell identifier as same as the dequeueReusableCellWithIdentifier in your code.
Swift 4, Swift 5
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .value1, reuseIdentifier: "Cell")
cell.textLabel?.text = user[indexPath.row].name
cell.detailTextLabel?.text = ">"
return cell
}
There are 4 Default UITableViewCell Style: default, value1, value2 & subtitle. Learn more at
https://developer.apple.com/documentation/uikit/uitableviewcell/cellstyle

Why is -didDeselectRowAtIndexPath not being called?

I created a fresh project (Xcode 4, Master-Detail application) just to see if I'm doing something wrong, but I still have the same problem. I want to call -reloadData when the user deselects a cell, so this is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"%s", __PRETTY_FUNCTION__);
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"%s", __PRETTY_FUNCTION__);
[tableView reloadData];
}
-(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"%s", __PRETTY_FUNCTION__);
return indexPath;
}
The problem is that didDeselectRowAtIndexPath and willDeselectRowAtIndexPath don't seem to be called. Is this the expected behavior? The docs for tableView:didDeselectRowAtIndexPath: state
Tells the delegate that the specified row is now deselected.
so I guess that it should work as I thought.
If you call deselectRowAtIndexPath:animated:, the delegate methods tableView:willDeselectRowAtIndexPath: and tableView:didDeselectRowAtIndexPath: message are not sent.
the documentation of tableView:willDeselectRowAtIndexPath: also says that
This method is only called if there is an existing selection when the
user tries to select a different row. The delegate is sent this method
for the previously selected row. You can use
UITableViewCellSelectionStyleNone to disable the appearance of the
cell highlight on touch-down.
It not worked for we when I used UITableViewCellSelectionStyleNone.
One other quirk that I've found — in IOS 5.1, at any rate — is that if you call reloadData on the table, you won't get didDeselectRowAtIndexPath for any selected rows. In my case, I adjust the cell layout slightly depending on whether it's selected or not, so I needed to manually do that work prior to reloading the table data.
I know this is an old question but I just ran into the same problem.
If you use
[tableView reloadData]
Then The table data is reloaded and no rows are selected behind the scenes - meaning
only
didSelectRowAtIndexPath
is ever called. I hope this helps someone who comes across this problem.
A clean way of solving this problem is to do the following:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath)
// Do your cell setup work here...
//If your cell should be selected...
if cellShouldBeSelected {
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
}
return cell
}
This solves this entire problem of a cell not responding to being deselected after a tableView.reloadData()call happens.
When any cell is selected the first time, the -[UITableViewDelegate tableView:didDeselectRowAtIndexPath:] method is not called, but the -[UITableViewDelegate tableView:didSelectRowAtIndexPath:]. Just after selecting one more cell, the didDeselectRowAtIndexPath is called right after the didSelectRowAtIndexPath.
This is OK.
But if you have to show a cell as selected at the begining, (e.q. using UITableViewCellAccessoryCheckmark), then, after selecting another cell you probably want the didDeselectRowAtIndexPath method being called the first time, to deselect the previous cell.
The solution!
You have to call the -[UITableView selectRowAtIndexPath:animated:scrollPosition:] in the -[UITableViewDataSource tableView:cellForRowAtIndexPath:] to notify that a wanted cell is already selected.
Objective-C
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// saving the current selected row
SelectedRow = indexPath.row;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
#pragma mark - UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
// preventing selection style
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = "Some text";
if (indexPath.row == SelectedRow) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// just wanted to make it selected, but it also can scroll to the selected position
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
return cell;
}
Swift 3.1
// MARK: - UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)!
cell.accessoryType = UITableViewCellAccessoryType.checkmark
selectedRow = indexPath.row
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)!
cell.accessoryType = UITableViewCellAccessoryType.none
}
// MARK: - UITableViewDataSource
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
// preventing selection style
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.textLabel?.text = "some text"
if (indexPath.row == selectedRow) {
cell.accessoryType = UITableViewCellAccessoryType.checkmark
// just wanted to make it selected, but it also can scroll to the selected position
tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)
}
return cell
}
You just have to set the selection to be "Multiple Selection" as Xcode allow you to deselect the cells in this mode only.
Xcode Screenshot
Set allowsMultipleSelection for that tableview to TRUE
self.tableView.allowsMultipleSelection = YES;
For me it's started working by adding ->super.setSelected(selected, animated: animated)
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)//This was missing
}
I think it's just simple mistake!
Why don't you use following:
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
Instead of using just "tableView" in that line?
I guess, and pretty sure that above line would give you the solution! hope this helped you, if you looked back at your old question!!!
Kudos! :)
First of all, you have to set allowsMultipleSelection is true and set delegate by below code
self.tableView.allowsMultipleSelection = true
self.tableView.delegate = self
If you use tableView.reloadData() in didSelectRowAt delegate method, remove this.
in your custom cell, use selected method.
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
//write your code here for selection method
}
By this method, your cell state is selected. If you again click on selected cell, then didDeSelect delegate method will call automatically.
One source of this issue is setting isSelected directly on the table view cell, rather than telling the table view to select the cell via selectRow(at:animated:scrollPosition:) or deselect it via deselectRow(at:animated:).
The cell's isSelected property is not the source of truth that the table view uses to determine whether to call the delegate's didDeselect method (although a cell whose isSelected is set does seem to prevent the table view from calling the delegate's didSelect method—meaning that the cell can get in a state where it is impossible to select or deselect via the UI).

Resources