Uitableview Checkmarks Disappear When Scrolling

UITableView Checkmarks disappear when scrolling


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->    UITableViewCell{
var cell : UITableViewCell = .........
if(boolArray[indexPath.row){
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
} else {
cell.accessoryType = UITableViewCellAccessoryType.None
}
}

Try this code.

How do I save checkmarks that disappear when scrolling in UITableView?

The cell accessoryType disappears because the reusability feature the UITableView use, in order to keep the selection follow the following code:

override func viewDidLoad()
{
super.viewDidLoad()
tableView.allowsMultipleSelection = true
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "celltwo")
cell.textLabel?.text = list[indexPath.row]
if let paths = tableView.indexPathsForSelectedRows
{
if (paths.contains(indexPath))
{
cell.accessoryType = .checkmark
}
else
{
cell.accessoryType = .none
}
}
else
{
cell.accessoryType = .none
}
cell.selectionStyle = .none
return cell
}


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{

if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCellAccessoryType.checkmark
{
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.none
}
else
{
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.checkmark
}
//remove deselection
//tableView.deselectRow(at: indexPath, animated: true)
}

Regard saving the selection, this info I guess should be persisted with your datasource in CoreData or UserDefaults.

TableView selected cells - checkmarks disappear when scrolled out of sight and new cell checked

It is happing because of reusability of Cell. Instead of setting Checkmark in didSelect try to set in the cellForRowAtIndexPath. Also you need to create model class like this to solve your problem

class ModelClass: NSObject {
var isSelected: Bool = false
//Declare other property that you are using cellForRowAtIndexPath
}

Now check this isSelected in cellForRowAtIndexPath like below.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath)
let row = indexPath.row
let modelClass = painArea[row]
cell.textLabel?.text = modelClass.name
if modelClass.isSelected {
cell.accessoryType = .Checkmark
}
else {
cell.accessoryType = .None
}
return cell
}

Now change your didSelect like this

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var modelClass = painArea[indexPath.row]
modelClass.isSelected = !modelClass.isSelected
self.tableView.reloadData()
populateDescription()
print(painArea[row])
}

Hope this will help you.

Accessories disappear when scrolling tableview | Swift 5

Last attempt:

As the selection is indicated by tick the isSelected property is actually redundant but you can use it to convert the Int value to a more suitable Bool. To be able to modify tick make it mutable.

And please name Portfolio in singular form

struct Portfolio: Decodable {

let person: String
let code: String
var tick: Int

var isSelected : Bool {
get { return tick == 2 }
set { tick = newValue ? 2 : 1 }
}

enum CodingKeys : String, CodingKey {
case person, code, tick
}
}

Replace selectRow with updateSelection(of:at:) which takes a Portfolio parameter and an indexPath. The table view is reloaded only if the network request was successful. I don't know what string the Alamofire request returns. It would be still more secure to first update the database and then update Portfolio.

func updateSelection(of portfolio: Portfolio, at indexPath: IndexPath) {
let url = portfolio.isSelected ? "https://example.com/example/selected" : "https://example.com/example/unselected"
let parameters: Parameters = [portfolio.code: portfolio.tick]

Alamofire.request(url, method: .post, parameters: parameters).responseString { response in
switch response.result {
case .success(let string): self.tableView.reloadRows(at: [indexPath], with: .none)
case .failure(let error): print(error)
}

}
}

In didSelectRowAt toggle isSelected (which updates tick implicitly) and update the database.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
sections[indexPath.section].items[indexPath.row].isSelected.toggle()
let portfolio = sections[indexPath.section].items[indexPath.row]
updateSelection(of: portfolio, at: indexPath)
}

You can leave the code in cellForRow

let item = sections[indexPath.section].items[indexPath.row]
cell.accessoryType = item.isSelected ? .checkmark : .none

but delete the method willDisplayCell

Checkmarks in tableview disappear when scrolling

See this comment in your code // Reflect selection in data model

You need to add logic in you data model to determine if the cell should display a checkmark or not.

And yes you are reusing cells unlike you think, see this line:

[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

EDIT:
You should declare a NSMutable array to hold all your section arrays:

NSMutableArray *data;

viewDidLoad

You will need to add a property to your data model in order to track if the cells should be selected or not. for example :

section1 = [NSMutableArray arrayWithObjects:@{@"title":@"Item 1",@"isSelected": @"N"},
@{@"title":@"Item 2",@"isSelected":@"N"},
@{@"title":@"Item 3",@"isSelected": @"N"},
@{@"title":@"Item 4",@"isSelected": @"N"}, nil];

After initializing your section arrays, append them to the data source

data = [NSMutableArray arrayWithObjects:section1, section2, section3,  section4, section5, section6, nil];

numberOfRowsInSection

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [data[section] count];
}

numberOfSectionsInTableView

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [data count];
}

cellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *simpleTableIdentifier = @"SimpleTableCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}
NSString * title = data[indexPath.section][indexPath.row][@"title"];
BOOL isSelected = [data[indexPath.section][indexPath.row][@"isSelected"] isEqualToString:@"Y"];

cell.textLabel.text = title;
if (!isSelected) {
cell.accessoryType = UITableViewCellAccessoryNone;
}else{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}

return cell;


}

didSelectRowAtIndexPath

- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {

[theTableView deselectRowAtIndexPath:[theTableView indexPathForSelectedRow] animated:NO];
UITableViewCell *cell = [theTableView cellForRowAtIndexPath:newIndexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// Reflect selection in data model
[data[newIndexPath.section] replaceObjectAtIndex:newIndexPath.row withObject:@{@"title":cell.textLabel.text,@"isSelected": @"Y"}];
} else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
// Reflect deselection in data model
[data[newIndexPath.section] replaceObjectAtIndex:newIndexPath.row withObject:@{@"title":cell.textLabel.text,@"isSelected": @"N"}];
}
}

When i scrolling on UITableview,the checkmark of multiple selected rows are disappears.how to solve this?

The problem lies in this piece of code:

if([_selectedstatearray containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}

You are checking if _selectedstatearray contains the specified indexPath while you store them as NSString [_selectedstatearray addObject:cellText];

Replace the code above with this:

NSString *text = [statearray objectAtIndex:indexPath.row];
if([_selectedstatearray containsObject:text]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}


Related Topics



Leave a reply



Submit