check / uncheck the check box by tapping the cell in table view and how to know which cell has checked or unchecked
In order to solve your issue, as @El Capitan mentioned, you will need to use the didSelectRowAtIndexPath
method to change its states. Your codes should look something along the lines of this:
// Declare a variable which stores checked rows. UITableViewCell gets dequeued and restored as you scroll up and down, so it is best to store a reference of rows which has been checked
var rowsWhichAreChecked = [NSIndexPath]()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell:FavCell = tableView.cellForRowAtIndexPath(indexPath) as! FavCell
// cross checking for checked rows
if(rowsWhichAreChecked.contains(indexPath) == false){
cell.checkBox.isChecked = true
rowsWhichAreChecked.append(indexPath)
}else{
cell.checkBox.isChecked = false
// remove the indexPath from rowsWhichAreCheckedArray
if let checkedItemIndex = rowsWhichAreChecked.indexOf(indexPath){
rowsWhichAreChecked.removeAtIndex(checkedItemIndex)
}
}
}
To redisplay cells which have been checked before after scrolling the rows out of view, at your cellForRowAtIndexPath
, perform the same checking against rowsWhichAreChecked
array and set its states accordingly.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:FavCell = self.FavTableView.dequeueReusableCellWithIdentifier("FCell") as! FavCell
cell.FLabel1.text=arrDict[indexPath.section] .valueForKey("favourite_name") as? String
cell.FLabel2.text=arrDict[indexPath.section] .valueForKey("favourite_address") as? String
if(rowsWhichAreChecked.contains(indexPath) == false){
cell.checkBox.isChecked = true
}else{
cell.checkBox.isChecked = false
}
}
return cell
}
EDITED ANSWER
I have got your code to work but I had to make some modifications to your Checkbox class and ViewController
Checkbox.swift
class CheckBoxButton: UIButton {
// Images
let checkedImage = UIImage(named: "CheckBoxChecked")! as UIImage
let uncheckedImage = UIImage(named: "CheckBoxUnChecked")! as UIImage
// Bool property
var isChecked: Bool = false {
didSet{
if isChecked == true {
self.setImage(uncheckedImage, forState: .Normal)
} else {
self.setImage(checkedImage, forState: .Normal)
}
}
}
override func awakeFromNib() {
self.userInteractionEnabled = false
// self.addTarget(self, action: #selector(CheckBoxButton.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
// self.isChecked = false
}
func buttonClicked(sender: UIButton) {
if sender == self {
if isChecked == true {
isChecked = false
} else {
isChecked = true
}
}
}
}
ViewController.swift
class FavVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var FavTableView: UITableView!
var rowsWhichAreChecked = [NSIndexPath]()
//var FData = [FavouritesData]()
var arrDict :NSMutableArray=[]
let cellSpacingHeight: CGFloat = 5 // cell spacing from each cell in table view
override func viewDidLoad() {
self.FavTableView.delegate = self
self.FavTableView.dataSource = self
super.viewDidLoad()
self.jsonParsingFromURL()
let nib = UINib(nibName:"FavCell", bundle: nil)
FavTableView.registerNib(nib, forCellReuseIdentifier: "FCell")
}
// web services method
func jsonParsingFromURL ()
{
// let token = NSUserDefaults.standardUserDefaults().valueForKey("access_token") as? String
let url = NSURL(string: "some url")
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
// print("done, error: \(error)")
if error == nil
{
dispatch_async(dispatch_get_main_queue())
{
self.arrDict=(try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSMutableArray
if (self.arrDict.count>0)
{
self.FavTableView.reloadData()
}
}
}
}
dataTask.resume()
//
// let StringUrl = "http"+token!
// let url:NSURL = NSURL(string: StringUrl)!
// if let JSONData = NSData(contentsOfURL: url)
// {
// if let json = (try? NSJSONSerialization.JSONObjectWithData(JSONData, options: [])) as? NSDictionary
// {
// for values in json
// {
// self.FData.append()
// }
// if let reposArray = json["data"] as? [NSDictionary]
// {
//
// for item in reposArray
// {
// let itemObj = item as? Dictionary<String,AnyObject>
//
// let b_type = itemObj!["business_type"]?.valueForKey("type")
//
// //self.Resultcount.text = "\(b_type?.count) Results"
//
// if (b_type as? String == "Taxis")
// {
//
// self.FData.append(FavouritesData(json:item))
//
// }
// }
// }
// }
// }
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
// return self.FData.count
return self.arrDict.count
}
// number of rows
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 1
}
// height for each cell
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
return cellSpacingHeight
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell:FavCell = self.FavTableView.dequeueReusableCellWithIdentifier("FCell") as! FavCell
cell.FLabel1.text=arrDict[indexPath.section] .valueForKey("favourite_name") as? String
cell.FLabel2.text=arrDict[indexPath.section] .valueForKey("favourite_address") as? String
let isRowChecked = rowsWhichAreChecked.contains(indexPath)
if(isRowChecked == true)
{
cell.checkbox.isChecked = true
cell.checkbox.buttonClicked(cell.checkbox)
}else{
cell.checkbox.isChecked = false
cell.checkbox.buttonClicked(cell.checkbox)
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell:FavCell = tableView.cellForRowAtIndexPath(indexPath) as! FavCell
// cross checking for checked rows
if(rowsWhichAreChecked.contains(indexPath) == false){
cell.checkbox.isChecked = true
cell.checkbox.buttonClicked(cell.checkbox)
rowsWhichAreChecked.append(indexPath)
}else{
cell.checkbox.isChecked = false
cell.checkbox.buttonClicked(cell.checkbox)
// remove the indexPath from rowsWhichAreCheckedArray
if let checkedItemIndex = rowsWhichAreChecked.indexOf(indexPath){
rowsWhichAreChecked.removeAtIndex(checkedItemIndex)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Check Uncheck buttons in uitableview's cell
For Check-Uncheck functionality only buttonClicked:
method is not enough. You will have also put the condition in cellForRowAtIndexPath:
method for which button is selected or which in unselected because cellForRowAtIndexPath:
method will call each time when you will scroll your UITableView
and cells will be refresh.
And i saw your previous question you're adding two buttons with two action not a good way just change the image of button for check-uncheck
.
So here is what i do for this -
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableView *tblView;
NSMutableArray *arrayCheckUnchek; // Will handle which button is selected or which is unselected
NSMutableArray *cellDataArray; // this is your data array
}
@end
Now in ViewController.m
class -
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arrayCheckUnchek = [[NSMutableArray alloc]init];
//Assign your cell data array
cellDataArray = [[NSMutableArray alloc]initWithObjects:@"cell-1",@"cell-2",@"cell-3",@"cell-4",@"cell-5", nil];
// setting all unchecks initially
for(int i=0; i<[cellDataArray count]; i++)
{
[arrayCheckUnchek addObject:@"Uncheck"];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [cellDataArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [cellDataArray objectAtIndex:indexPath.row];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(270.0, 7.0, 30.0, 30.0)];
if([[arrayCheckUnchek objectAtIndex:indexPath.row] isEqualToString:@"Uncheck"])
[button setImage:[UIImage imageNamed:@"uncheck_icon"] forState:UIControlStateNormal];
else
[button setImage:[UIImage imageNamed:@"check_icon"] forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
return cell;
}
-(void)buttonClicked:(id)sender
{
//Getting the indexPath of cell of clicked button
CGPoint touchPoint = [sender convertPoint:CGPointZero toView:tblView];
NSIndexPath *indexPath = [tblView indexPathForRowAtPoint:touchPoint];
// No need to use tag sender will keep the reference of clicked button
UIButton *button = (UIButton *)sender;
//Checking the condition button is checked or unchecked.
//accordingly replace the array object and change the button image
if([[arrayCheckUnchek objectAtIndex:indexPath.row] isEqualToString:@"Uncheck"])
{
[button setImage:[UIImage imageNamed:@"check_icon"] forState:UIControlStateNormal];
[arrayCheckUnchek replaceObjectAtIndex:indexPath.row withObject:@"Check"];
}
else
{
[button setImage:[UIImage imageNamed:@"uncheck_icon"] forState:UIControlStateNormal];
[arrayCheckUnchek replaceObjectAtIndex:indexPath.row withObject:@"Uncheck"];
}
}
And finally it will look like -
check and uncheck buttons in table view controller
In daysRemainderTableView
take imageview with name daysSelectionimageView
.This is example to select and deselect rows in tableviewcell .
@IBOutlet weak var daysRemainderTableView: UITableView!
var days = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
var selectedDaysArray = [Int]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return days.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RemainderDaysCell", for: indexPath)as! RemainderDaysCell
cell.remainderDaysLabel.text = "\(days[indexPath.row])"
if selectedDaysArray.contains(indexPath.row){
cell.daysSelectionimageView.image = #imageLiteral(resourceName: "selectedImage")
}else{
cell.daysSelectionimageView.image = #imageLiteral(resourceName: "ring")
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? RemainderDaysCell
{
if selectedDaysArray.isEmpty{
self.selectedDaysArray = [Int]()
}
if selectedDaysArray.contains(indexPath.row){
if let indexElement = selectedDaysArray.index(of: indexPath.row){
cell.daysSelectionimageView.image = #imageLiteral(resourceName: "ring")
selectedDaysArray.remove(at: indexElement)
}
}else{
cell.daysSelectionimageView.image = #imageLiteral(resourceName: "selectedImage")
selectedDaysArray.append(indexPath.row)
}
}
}
I am checking selectedDaysArray
in cellforrow at indexpath and didSelectRow ai indexpath ,if selectedDaysArray has selected index i am removing element if it is not i am appending indexemement to selectedDaysArray.
Check and uncheck the same UITableViewCell
Where your datasource is load
do this
arrSelected = [[NSMutableArray alloc] init];
for (int i = 0; i <arrSong.count; i++) {
[arrSelected addObject:[NSNumber numberWithBool:NO]];
}
In your cell for indexpath do this
if ([[arrSelected objectAtIndex:indexPath.row] boolValue] == YES) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
To select/deselect do thisin you tableview:didselect
if ([[arrSelected objectAtIndex:indexPath.row] boolValue] == YES) {
[arrSelected replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:NO]];
}
else{
[arrSelected replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:YES]];
}
TableView CheckMark and Uncheck With Scroll Up Still Checked Cell Value In Ios Swift 4
I think if someone were to run your code it would not show any error. But with real data it probably will. The reason is the way you store your checkmarks. You store the data of a row into the temp
array when you should be storing the actualy indexPath
of the array so that only that row gets the checkmark. In your case, if a row has 1
inside it's label and you click on it, that cell will be highlighted. Now if you start scrolling and another cell contains 1
then that row will also be highlighted.
I have modified your example for the case of a single section. If there is more than one section, you need to store the indexPath
instead of indexPath.row
.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "id")
cell = UITableViewCell.init(style: .default, reuseIdentifier: "id")
cell?.textLabel?.text = String(numarr[indexPath.row])
if temp.contains(indexPath.row) {
cell?.accessoryType = .checkmark
} else {
cell?.accessoryType = .none
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if temp.contains(indexPath.row) {
cell?.accessoryType = .none
temp.remove(at: indexPath.row)
} else {
cell?.accessoryType = .checkmark
temp.append(indexPath.row)
}
}
UITableViewCell Accessory Type Checked on Tap & Set other unchecked
I would keep track of the data that should be checked and change the cell in tableView:didSelectRowAtIndexPath: and update which data is checked in tableView:cellForRowAtIndexPath: like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// do usual stuff here including getting the cell
// determine the data from the IndexPath.row
if (data == self.checkedData)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// determine the selected data from the IndexPath.row
if (data != self.checkedData) {
self.checkedData = data;
}
[tableView reloadData];
}
Uncheck UITableview custom checkbox option in Swift
Instead of let cell = tableView.dequeueReusableCellWithIdentifier...
I would use
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomCellVC
This way you get a reference to the cell you want to change the image in. tableView.dequeueReusableCellWithIdentifier
is meant to be used in delegate method tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
when you want to recycle your cells for better performance.
Also cell.ivRiskCellImage.image!.isEqual(UIImage(named: "UncheckedBox"))
doesn't work, because UIImage(named: "UncheckedBox")
creates a new UIImage, which isn't the same as the UIImage you want to check it against.
Related Topics
iOS 7.0 and Arc: Uitableview Never Deallocated After Rows Animation
Physicsbody Doesn't Adhere to Node's Anchor Point
Using Two Versions of a Cocoapod Dependency
Xcode5 Simulator: Unknown Option Character 'X' In: -Xlinker
Fbsopenapplicationerrordomain Code=3
Multiple Uialertcontrollers in iOS
Using Uisheetpresentationcontroller in Swiftui
Show Data in Uipickerview Second Component Based on First Component Selection
Duplicate Interface Definition for Class 'Gtmhttpuploadfetcher'
Code Signing Issue in Xcode Version 8
How to Change iPhone Uitableview Delete Button Title While Editing It
Remove Uiwebview's Internal Cache
Xcode 7 Beta 6, Dyld _Nsarray0_ Crash
Why Was Uitextfield's Text Property Changed to an Optional in Swift 2
Safari Web View Opening When Logging to Fb Through iOS 9