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
How to Detect Apps First Launch in iOS
Checking for Multiple Asynchronous Responses from Alamofire and Swift
Copy Nsattributedstring in Uipasteboard
Why Is Uitextfield.Text an Optional
Amazon Aws iOS Sdk: How to List All File Names in a Folder
Negative Number Modulo in Swift
How to Create a Hex Color String Uicolor Initializer in Swift
Install Apps on Device Without Itunes
Can't Pass Data Correctly to Modal Presentation Using Foreach and Coredata in Swiftui
Swift 3 - Comparing Date Objects
How to Make Post Nsurlrequest with 2 Parameters
Prevent Uialertcontroller to Dismiss
You Are Not Authorised to Use This Service Itunes App Upload Error
How to Call Presentviewcontroller from Within a Uicollectionviewcell
In Swift, How to Let Other Apps Continue to Play Audio When My App Is Open