How to apply rating stars into UITableViewCells - ios

Hi I want apply rating stars into UITableViewCell.
Is any sample available for it?
I tried some code but it's not working.
Please help.
My Code:
#import "ViewController.h"
#import "starsInCell.h"
#interface ViewController ()
{
starsInCell *cell;
NSMutableArray *mainArray,*BtnsArray;
}
#end
#implementation ViewController
#synthesize TableList;
- (void)viewDidLoad {
[super viewDidLoad];
TableList.delegate = self;
TableList.dataSource = self;
mainArray = [[NSMutableArray alloc] initWithObjects:#"",#"", #"",#"",#"",nil];
BtnsArray = [[NSMutableArray alloc] initWithObjects:#"false",#"false",#"false",#"false",#"false", nil];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return mainArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Cell";
cell =[TableList dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"starsInCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//cell.textLabel.text = #"1";
//cell.backgroundColor = [UIColor orangeColor];
NSString *btn1str = [BtnsArray objectAtIndex:0];
NSString *btn2str = [BtnsArray objectAtIndex:1];
NSString *btn3str = [BtnsArray objectAtIndex:2];
NSString *btn4str = [BtnsArray objectAtIndex:3];
NSString *btn5str = [BtnsArray objectAtIndex:4];
[self setImages:btn1str :cell.btn1];
[self setImages:btn2str :cell.btn2];
[self setImages:btn3str :cell.btn3];
[self setImages:btn4str :cell.btn4];
[self setImages:btn5str :cell.btn5];
[cell.btn1 addTarget:self action:#selector(btn1Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn2 addTarget:self action:#selector(btn2Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn3 addTarget:self action:#selector(btn3Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn4 addTarget:self action:#selector(btn4Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn5 addTarget:self action:#selector(btn5Clicked:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
}
-(void)btn1Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn2Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn3Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn4Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn5Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)setImages:(NSString*)string1 :(UIButton*)button1{
if ([string1 isEqualToString:#"false"]){
[button1 setImage:[UIImage imageNamed:#"Star1.png"] forState:UIControlStateNormal];
}else{
[button1 setImage:[UIImage imageNamed:#"Star2.png"] forState:UIControlStateNormal];
}
}
#end

I would recommend you to do this yourself only if you are new in development and you want to build your logic, so instead of using any readymade library you can follow below steps.
First add 5 buttons on your cell and set bordered star image for each buttons default state and then change buttons state to Selected and set filled star image. (Do same for 5 buttons). After you done this make sure you change all buttons state to Default.
Add action buttonStarRatingsClicked for all 5 buttons.
Create outlet collection buttonCollectionStarRatings for each button in starsInCell class.
Add below method in your viewController which is showing tableView having stars on each cell.
- (IBAction)buttonStarRatingsClicked:(id)sender {
UIButton *buttonStarRatings = (UIButton*) sender;
//Here you will need to get cell to access buttonCollectionStarRatings
UITableViewCell *cell = (UITableViewCell*) [[buttonStarRatings superView] superView];
//Check is clicked button is selected
if ([buttonStarRatings isSelected]) {
if (buttonStarRatings.tag == 0) { //Check is clicked button is first button
//Check if Next button of selected button is selected
if ([cell.buttonCollectionStarRatings[buttonStarRatings.tag+1] isSelected]) {
#autoreleasepool {
for (int i = (int)buttonStarRatings.tag+1; i < [cell.buttonCollectionStarRatings count]; i++) {
UIButton *buttonStarRating = cell.buttonCollectionStarRatings[i];
[buttonStarRating setSelected:NO];
}
}
} else {
//If selected button is first button and is selected then do not take any action as atlease one star should be selected.
}
} else if (buttonStarRatings.tag == 4) { //Check is clicked button is last button
[buttonStarRatings setSelected:NO];
} else { //Selected button is one of the button between first and last
//Check if Next button of selected button is selected
if ([cell.buttonCollectionStarRatings[buttonStarRatings.tag+1] isSelected]) {
#autoreleasepool {
for (int i = (int)buttonStarRatings.tag; i < [cell.buttonCollectionStarRatings count]; i++) {
UIButton *buttonStarRating = cell.buttonCollectionStarRatings[i];
[buttonStarRating setSelected:NO];
}
}
} else {
[buttonStarRatings setSelected:NO];
}
}
} else {
if (buttonStarRatings.tag == 0) { //Check is clicked button is first button
[buttonStarRatings setSelected:YES];
} else if (buttonStarRatings.tag == 4) { //Check is clicked button is last button
#autoreleasepool {
for (UIButton *buttonStarRating in cell.buttonCollectionStarRatings) {
[buttonStarRating setSelected:YES];
}
}
} else { //Selected button is one of the button between first and last
#autoreleasepool {
for (int i = 0; i <= (int)buttonStarRatings.tag; i++) {
UIButton *buttonStarRating = cell.buttonCollectionStarRatings[i];
[buttonStarRating setSelected:YES];
}
}
}
}
}
The above part will allow you to select star ratings on each cell, next step is managing the selected stars on each cell while scrolling the table.

Related

Dynamic expandable and collapsed table view cells?

I developed expandable and collapsed table view for dynamic data comes from the server. I'm displaying state names in header view successfully, but I can't displaying child data that is districts related to state names.
I followed Link for this http://www.iostute.com/2015/04/expandable-and-collapsable-tableview.html
My data is
_response = #{#"Response":#{#"status":#"SUCCESS",#"error_code":#"0",#"message":#"SUCCESS",#"Array":#[
#{#"state_id":#"0",#"state_name":#"null",#"district_id":#"0",#"district_name":#"null"},
#{#"state_id":#"01",#"state_name":#"State1",#"district_id":#"001",#"district_name":#"State1District1"},
#{#"state_id":#"02",#"state_name":#"State2",#"district_id":#"004",#"district_name":#"State2District1"},
#{#"state_id":#"02",#"state_name":#"State2",#"district_id":#"005",#"district_name":#"State3District1"},
#{#"state_id":#"01",#"state_name":#"State1",#"district_id":#"002",#"district_name":#"State1District2"},
#{#"state_id":#"01",#"state_name":#"State1",#"district_id":#"003",#"district_name":#"State1District3"},
#{#"state_id":#"03",#"state_name":#"State3",#"district_id":#"006",#"district_name":#"State3District1"},
#{#"state_id":#"04",#"state_name":#"State4",#"district_id":#"008",#"district_name":#"State4District1"},
#{#"state_id":#"04",#"state_name":#"State4",#"district_id":#"009",#"district_name":#"State4District2"},
#{#"state_id":#"04",#"state_name":#"State4",#"district_id":#"010",#"district_name":#"State4District3"},
#{#"state_id":#"05",#"state_name":#"State5",#"district_id":#"011",#"district_name":#"State5District1"},
#{#"state_id":#"05",#"state_name":#"State5",#"district_id":#"012",#"district_name":#"State5District2"},
#{#"state_id":#"03",#"state_name":#"State3",#"district_id":#"007",#"district_name":#"State3District2"}]}, #"count":#"6"};
My code is
if ([[[_response objectForKey:#"Response"] objectForKey:#"status"] isEqualToString:#"SUCCESS"] && (!(_integer == 0))) {
_stateID = [[NSMutableArray alloc] init];
_stateName = [[NSMutableArray alloc] init];
_districtID = [[NSMutableArray alloc] init];
_districtName = [[NSMutableArray alloc] init];
_stateIdStateNameDic = [[NSMutableDictionary alloc]init];
//Add arrays to array to remove null values dynamically
NSArray *arr = [[NSArray alloc]initWithObjects:_stateID, _stateName, _districtID, _districtName, nil];
for (int i=0; i<_integer; i++) {
[_stateID addObject:[[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"state_id"]];
[_stateName addObject:[[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"state_name"]];
[_districtID addObject:[[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"district_id"]];
[_districtName addObject:[[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"district_name"]];
//Remove null values
for (int j=0; j<arr.count; j++) {
for (NSMutableArray *ar in arr) {
if ([[ar objectAtIndex:i] isKindOfClass:[NSNull class]] || [[ar objectAtIndex:i] isEqualToString:#"null"] || [[ar objectAtIndex:i] isEqualToString:#"0"]) {
[ar addObject:#""];
[ar removeObjectAtIndex:i];
}
}
}
}
//Add arrays to mutable array to remove empty objects
NSMutableArray *marr = [[NSMutableArray alloc]initWithObjects:_stateID, _stateName, _districtID, _districtName, nil];
//Remove empty objects from all arrays
for (int j=0; j<marr.count; j++) {
for (int i=0; i<[[marr objectAtIndex:j] count]; i++) {
if ([[[marr objectAtIndex:j] objectAtIndex:i] isEqualToString:#""]) {
[[marr objectAtIndex:j] removeObjectAtIndex:i];
}
}
}
//Remove duplicates from state names array
_stateName = [_stateName valueForKeyPath:#"#distinctUnionOfObjects.self"];
NSString *districtName = #"";
NSString * superater = #"&&";
_mdic = [[NSMutableDictionary alloc]init];
for (int j=0; j<_stateName.count; j++) {
for (int i=0; i<_integer; i++) {
if ([[_stateName objectAtIndex:j] isEqualToString:[[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"state_name"]]) {
//Remove district name if empty or null
if ([districtName isEqualToString:#""] || [districtName isEqual:[NSNull null]]) {
districtName = [[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"district_name"];
if ([districtName isEqual:[NSNull null]] || [districtName isEqualToString:#"null"]) {
districtName = #"";
}
} else {
//Add all districts with superater &&
districtName = [districtName stringByAppendingString:[NSString stringWithFormat:#"%#%#", superater, [[[[_response objectForKey:#"Response"] objectForKey:#"Array"] objectAtIndex:i] objectForKey:#"district_name"]]];
}
}
}
//Create district names dictionary with state name keys
[_mdic setValue:districtName forKey:[_stateName objectAtIndex:j]];
districtName = #"";
}
NSLog(#"_mdic %#", _mdic);
_arrayForBool=[[NSMutableArray alloc]init];
//Save bool value " NO " based on sectionTitleArray count.
for (int i=0; i<[_stateName count]; i++) {
[_arrayForBool addObject:[NSNumber numberWithBool:NO]];
}
dispatch_async(dispatch_get_main_queue(), ^{
[_availableOrdersTableView reloadData];
});
} else {
}
// TableView delegates
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [_mdic count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Number of rows in each section
if ([[_arrayForBool objectAtIndex:section] boolValue]) {
NSLog(#"%#", [_stateName objectAtIndex:section]);
NSLog(#"%#", _mdic);
NSArray *mdicKeys = [_mdic allKeys];
for (int i=0; i<_mdic.count; i++) {
if ([[mdicKeys objectAtIndex:i] isEqualToString:[_stateName objectAtIndex:section]]) {
NSString *str = [_mdic objectForKey:[_stateName objectAtIndex:section]];
NSLog(#"%#", str);
_subDistrictArr = [str componentsSeparatedByString:#"&&"];
}
}
NSLog(#"_subDistrictIDArr %#", _subDistrictArr);
return _subDistrictArr.count;
} else {
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Create cell
static NSString *cellid=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellid];
if (cell==nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellid];
}
BOOL manyCells = [[_arrayForBool objectAtIndex:indexPath.section] boolValue];
/********** If the section supposed to be closed *******************/
if(!manyCells)
{
cell.backgroundColor=[UIColor clearColor];
cell.textLabel.text=#"";
}
/********** If the section supposed to be Opened *******************/
else {
cell.textLabel.text=[_subDistrictArr objectAtIndex:indexPath.row];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
cell.textLabel.font=[UIFont systemFontOfSize:20.0f];
} else {
cell.textLabel.font=[UIFont systemFontOfSize:15.0f];
}
cell.backgroundColor=[UIColor whiteColor];
cell.selectionStyle=UITableViewCellSelectionStyleNone ;
}
cell.textLabel.textColor=[UIColor blackColor];
/********** Add a custom Separator with cell *******************/
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(15, 48, _availableOrdersTableView.frame.size.width-15, 1)];
separatorLineView.backgroundColor = [UIColor blackColor];
[cell.contentView addSubview:separatorLineView];
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *sectionView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, _availableOrdersTableView.frame.size.width, 50)];
sectionView.backgroundColor = [UIColor clearColor];
sectionView.tag=section;
UILabel *viewLabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, _availableOrdersTableView.frame.size.width, sectionView.frame.size.height)];
viewLabel.backgroundColor=[UIColor clearColor];
viewLabel.textColor=[UIColor blackColor];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
viewLabel.font=[UIFont systemFontOfSize:25];
} else {
viewLabel.font=[UIFont systemFontOfSize:15];
}
viewLabel.text=[NSString stringWithFormat:#"%#", [_stateName objectAtIndex:section]];
_stateIDString = [_stateID objectAtIndex:section];
NSLog(#"stateIDString %#", _stateIDString);
[sectionView addSubview:viewLabel];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(sectionView.frame.size.width-45, (sectionView.frame.size.height-25)/2, 18, 17)];
imgView.tag = section;
imgView.image = [UIImage imageNamed:#"DA"];
[sectionView addSubview:imgView];
} else {
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(sectionView.frame.size.width-35, (sectionView.frame.size.height-25)/2, 18, 17)];
imgView.tag = section;
imgView.image = [UIImage imageNamed:#"DA"];
[sectionView addSubview:imgView];
}
/********** Add a custom Separator with Section view *******************/
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, sectionView.frame.size.height, _availableOrdersTableView.frame.size.width, 1)];
separatorLineView.backgroundColor = [UIColor blackColor];
[sectionView addSubview:separatorLineView];
/********** Add UITapGestureRecognizer to SectionView **************/
UITapGestureRecognizer *headerTapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(sectionHeaderTapped:)];
[sectionView addGestureRecognizer:headerTapped];
return sectionView;
}
- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:gestureRecognizer.view.tag];
// _gestureInteger = gestureRecognizer.view.tag;
if (indexPath.row == 0) {
BOOL collapsed = [[_arrayForBool objectAtIndex:indexPath.section] boolValue];
for (int i=0; i<[_stateName count]; i++) {
if (indexPath.section==i) {
[_arrayForBool replaceObjectAtIndex:i withObject:[NSNumber numberWithBool:!collapsed]];
}
}
[_availableOrdersTableView reloadSections:[NSIndexSet indexSetWithIndex:gestureRecognizer.view.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
// [_availableOrdersTableView reloadData];
}
}
I have two solution for this
(1) initially you put numberofrow for any section is zero and after click on any section you can add row for for clicked section.
(2) number of section will be one and you need to use two cell "cellwithheaderonly" and "cellwithheaderandsubpart" initially you will use "cellwithheaderonly" and when user will click on any cell you need to use "cellwithheaderandsubpart"
You can take reference from following URL
Expanding and Collapsing table view cells in ios
https://www.anexinet.com/blog/expandable-collapsible-uitableview-sections/
You have to maintain an array given below : -
lat arr = [[“name”:”firstRow” , “subRowArray”:[1,2,3,4]],[“name”:”secondRow” , “subRowArray”:[1,2,3,4]],[“name”:”thirdRow” , “subRowArray”:[1,2,3,4]]]
then expand and collapse according to your array .
if would you like to use library then go for expendable Tableview

How to change image on button pressed with cell reused

There is a problem. I need at the touch of a button to add to the array and at the button to change the image.
I do it this way:
- (IBAction)addUserAction:(UIButton *)sender {
CGPoint touchPoint = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *clickedButtonIndexPath = [self.tableView indexPathForRowAtPoint:touchPoint];
NSInteger row = clickedButtonIndexPath.row;
UserCell* selectedCell = [self.tableView cellForRowAtIndexPath:clickedButtonIndexPath];
NSString* login = selectedCell.loginLabel.text;
BOOL userIsExist = selectedCell.isExist;
for (QBUUser* user in self.users) {
if ([login isEqualToString:user.login]) {
if (!userIsExist) {
[self.assistant.usersInCurrentChat addObject:user];
userIsExist = YES;
UIButton* button = self.buttons[clickedButtonIndexPath.row];
[button setImage:[UIImage imageNamed:#"delete_icon_64x64.png"] forState:UIControlStateNormal];
self.buttons[clickedButtonIndexPath.row] = button;
} else{
[self.assistant.usersInCurrentChat removeObject:user];
userIsExist = NO;
UIButton* button = self.buttons[clickedButtonIndexPath.row];
[button setImage:[UIImage imageNamed:#"add_button_64x64.png"] forState:UIControlStateNormal];
self.buttons[clickedButtonIndexPath.row] = button;
}
}
}
selectedCell.isExist = userIsExist;
}
my Code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UserCell* cell = [tableView dequeueReusableCellWithIdentifier:#"userCell1"];
if(!cell){
cell = [[UserCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"userCell1"];
}
QBUUser* user = [self.users objectAtIndex:indexPath.row];
cell.loginLabel.text = [NSString stringWithFormat:#"%#", user.login];
NSInteger currentTimeInterval = [[NSDate date] timeIntervalSince1970];
NSInteger userLastRequestAtTimeInterval = [[user lastRequestAt] timeIntervalSince1970];
// if user didn't do anything last 1 minute (60 seconds)
if((currentTimeInterval - userLastRequestAtTimeInterval) > 60){
cell.statusImageView.image = [UIImage imageNamed:#"offline_icon_45x45.png"];
} else{
cell.statusImageView.image = [UIImage imageNamed:#"online_icon_32x32.png"];
}
NSInteger row = indexPath.row;
if ([self.buttons[indexPath.row] isEqual:[NSNull null]]) {
self.buttons[indexPath.row] = cell.button;
} else {
cell.button = self.buttons[indexPath.row];
}
return cell;
}
But the cell "reused" and I get the result as in the picture my bug
How do I fix this ?

uicollectionview cells not showed after updates as per requirement after reload data

i have a products catalogue that is shown in collection view, User may change the category or sub category for new products and they are populating in collection view perfectly.
now user may choose the quantity of any specific product in numbers as 1, 2, 3 or more to buy.
for this i set UIButton action in collection view cell to take users input in UITextfield inside Cell.
all works perfectly, actually i have different number of products as per Category wise, and most of the time i have to scroll to see products in collection view.
when ever the quantity of any product or more than one products are set they are just perfect as i want in each Cell.
** Updated Problem:**
if i change the category or sub category to see other products in collection view now this condition never satisfies in both uibutton action method and in cellForItemAtIndexPath method.
here is problem:
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{} // this condition is creating problem on category or sub category change.
that how i am working:
Custom CollectionView class
#interface MyCell : UICollectionViewCell
#property (retain, nonatomic) UIButton *btn1;
#property (retain, nonatomic) UITextField *txt1;
#end
implementation
#implementation MyCell
#synthesize btn1, txt1;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
CGRect btn1Rect = CGRectMake(190, 230 , 35 , 35);
btn1 = [[UIButton alloc] initWithFrame:btn1Rect];
btn1.tag=11;
[btn1 setBackgroundImage:[UIImage imageNamed:#"BtnPlus.png"] forState:UIControlStateNormal];
//btn1.layer.borderWidth = 1.0f;
CGRect txt1Rect = CGRectMake(143, 230 , 45 , 30);
txt1 = [[UITextField alloc] initWithFrame:txt1Rect];
txt1.tag=13;
txt1.font=[UIFont fontWithName:#"Superclarendon" size:18];
txt1.textAlignment = NSTextAlignmentCenter;
txt1.textColor = [UIColor blueColor];
//txt1.layer.borderWidth = 1.0f;
}
return self;
}
in ViewController implementation
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CellID" forIndexPath:indexPath];
[[cell btn1] addTarget:self action:#selector( btnPlus:event:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:cell.btn1];
cell.txt1.text = #"0";
for (i = 0; i < [updatedCodes count]; i++)
{
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
}
[cell.contentView addSubview:cell.txt1];
return cell;
}
the UIButton Action Method is
-(void)btnPlus:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:myCollection];
btnIndex = [myCollection indexPathForItemAtPoint: currentTouchPosition];
MyCell *cell = (MyCell*)[myCollection cellForItemAtIndexPath:btnIndex];
NSString *newCode = [code objectAtIndex:btnIndex.row];
NSString *newQty = cell.txt1.text;
if ([updatedCodes containsObject:newCode])
{
for (i = 0; i < [updatedCodes count]; i ++)
{
if ([updatedCodes objectAtIndex:i] == newCode)
{
qnty = [newQty integerValue];
qnty = qnty + 1;
cell.txt1.text = [NSString stringWithFormat:#"%d", qnty];
newQty = cell.txt1.text;
[updatedQty replaceObjectAtIndex:i withObject:newQty];
}
}
if (![indexPaths containsObject:btnIndex])
{
[indexPaths addObject:btnIndex];
}
}
else
{
[updatedCodes addObject:newCode];
qnty = [newQty integerValue];
qnty = qnty + 1;
cell.txt1.text = [NSString stringWithFormat:#"%d", qnty];
newQty = cell.txt1.text;
[updatedQty addObject:newQty];
if (![indexPaths containsObject:btnIndex])
{
[indexPaths addObject:btnIndex];
}
}
[myCollection reloadItemsAtIndexPaths:indexPaths];
}
NOTE:
Code, indexPaths ,updatedCodes and updatedQty are NSMutableArrays
Any suggestion / Help about this problem will be greatly appreciated.
waiting for swift help….. :(
The problem is here
if ([indexPaths count] > 0)
{
for (i = 0; i < [updatedCodes count]; i++)
{
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
}
}
As when this array has records it will go in within this IF statement and will skip the else statement where you are actually setting your cell.txt1.text = #"0". Easiest fix would be to put next line of code just before the for loop
cell.txt1.text = #"0";
Like this
if ([indexPaths count] > 0)
{
cell.txt1.text = #"0";
for (i = 0; i < [updatedCodes count]; i++)
{
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
}
}
answering your own question may be not good but i figured out my problem and resolve it myself
so posting here the issue for some one else who is suffering in same problem….
this is all i change in my code
in view controller implemention
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
with this
if ([[code objectAtIndex:indexPath.row] isEqualToString:[updatedCodes objectAtIndex:i]])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
and same change in Button Action method as
if ([newCode isEqualToString:[updatedCodes objectAtIndex:i]])
{
// do something
}

SKSTableView Scrolling Issue

I am currently using this custom/ expandable tableview code called SKSTableView which can be found at Here
Here's the issue, when I fill the table with over 10 rows, the UI Locks up and the scrolling begins to be extremely laggy. I can't seem to be able to track down the issue, but I am thinking it has something to do with reusing the cell.
Here's some code that will hopefully help.
-SKSTableView hasn't changed
-Below is the implementation in the actual file /Home Screen of app
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Bar *bar = [bars objectAtIndex:indexPath.row];
NSArray *friendsAtBar = (NSArray*)bar.friends;
static NSString *cellIdentifier = #"SKSTableViewCell";
SKSTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell){//If no cell, create a new one
cell = [[SKSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
UIColor *cellBackgroundColor = [UIColor colorWithWhite:( 30/255.0) alpha:1.0];
UIColor *cellTextColor = [UIColor colorWithWhite:0.80 alpha:1.0];
UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 73, 320, 2)];
bottomLine.backgroundColor = [UIColor colorWithWhite:( 50/255.0) alpha:1.0];
cell.nameLabel.textColor = cellTextColor;
cell.friendsLabel.textColor = cellTextColor;
cell.backgroundColor = cellBackgroundColor;
cell.selectionBanner.backgroundColor = cellBackgroundColor;
[cell addSubview:bottomLine];
[cell.goingButton addTarget:self
action:#selector(goingButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.nameLabel.frame = nameStartFrame;
}
if (friendsAtBar != nil && friendsAtBar.count != 0)
cell.isExpandable = YES;
else
cell.isExpandable = NO;
cell.nameLabel.text = bar.name;
//cell.userInteractionEnabled = YES;
if (friendsAtBar.count == 1) // If only 1 friend is going, say friend, if more than 1 friend is going say friends
cell.friendsLabel.text = [NSString stringWithFormat:#"%lu friend going",(unsigned long)friendsAtBar.count];
else if (friendsAtBar.count > 1)
cell.friendsLabel.text = [NSString stringWithFormat:#"%lu friends going",(unsigned long)friendsAtBar.count];
else {
cell.friendsLabel.text = #"";
//cell.nameLabel.frame = CGRectMake(20, 26, 200, 23);
}
//cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.tag = indexPath.row;
[self deselectGoingButton:cell.goingButton];
if ([bar.objectID isEqualToString:[currentUser objectForKey:#"currentBarID"]] && [self under15Hours:[currentUser objectForKey:#"barTimeStamp"]])
{
goingToBarID = bar.objectID; // HERE
//NSLog(#"goingToBarID from cell: %#",goingToBarID);
selectedGoingToButton = cell.goingButton;
[self selectGoingButton:cell.goingButton];
}
cell.goingButton.tag = indexPath.row;
cell.selectionBanner.tag = indexPath.row;
return cell;
}
#pragma mark - TableView - Subrow
- (NSInteger)tableView:(SKSTableView *)tableView numberOfSubRowsAtIndexPath:(NSIndexPath *)indexPath {
if (bars != nil && bars.count != 0) {
Bar *bar = [bars objectAtIndex:indexPath.row];
return bar.friends.count;
}
else
return 0;
} // PARSE IMPACTED
- (UITableViewCell *)tableView:(UITableView *)tableView cellForSubRowAtIndexPath:(NSIndexPath *)indexPath {
//NSMutableDictionary *bar = [bars objectAtIndex:indexPath.row];
Bar *bar = [bars objectAtIndex:indexPath.row];
NSArray *friendsAtBar = (NSArray*)bar.friends;
//UIColor *cellBackgroundColor = [UIColor colorWithWhite:( 20/255.0) alpha:1.0];
//UIColor *cellTextColor = [UIColor colorWithWhite:0.85 alpha:1.0];
UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 73, 320, 2)];
bottomLine.backgroundColor = [UIColor colorWithWhite:( 50/255.0) alpha:1.0];
static NSString *cellIdentifier = #"FriendsGoingCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UIView *cellView;
UILabel *nameLabel;
UILabel *usernameLabel;
UIButton *callButton;
UIButton *textButton;
if (!cell){//If no cell, make a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cellView = [self createSubRowView];
nameLabel = [cellView.subviews objectAtIndex:1];
usernameLabel = [cellView.subviews objectAtIndex:2];
usernameLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
callButton = [cellView.subviews objectAtIndex:3];
textButton = [cellView.subviews objectAtIndex:4];
[cell addSubview:cellView];
[cell addSubview:bottomLine];
}
//cell.backgroundColor = cellBackgroundColor;
cell.tag = 2;
//PFUser *user = [friendsAtBar objectAtIndex:indexPath.subRow-1];
Friend *user = [friendsAtBar objectAtIndex:indexPath.subRow-1];
//UILabel *nameLabel = [cellView.subviews objectAtIndex:1];
//nameLabel.text = [[friendsAtBar objectAtIndex:indexPath.subRow-1] objectForKey:#"username"];
nameLabel.text = [NSString stringWithFormat:#"%#",user.compositeName];
//nameLabel.textColor = cellTextColor;
// UILabel *usernameLabel = [cellView.subviews objectAtIndex:2];
usernameLabel.text = user.userName;
//UIButton *callButton = [cellView.subviews objectAtIndex:3];
callButton.tag = indexPath.subRow-1;
//UIButton *textButton = [cellView.subviews objectAtIndex:4];
textButton.tag = indexPath.subRow-1;
return cell;
}
[self createSubView]
- (UIView *)createSubRowView {
UIView *cellView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, [rowHeight floatValue])];
UIColor *fontColor = [UIColor colorWithWhite:0.85 alpha:1.0];
UIView* bgview = [[UIView alloc] initWithFrame:cellView.frame];
bgview.backgroundColor = [UIColor colorWithWhite:0.15 alpha:1.0];
[cellView addSubview:bgview];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 16, 180, 23)];
nameLabel.textColor = fontColor;
nameLabel.font = [UIFont boldSystemFontOfSize:17];
[cellView addSubview:nameLabel];
UILabel *goingTimeStampLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 41, 180, 16)];
goingTimeStampLabel.textColor = fontColor;
goingTimeStampLabel.font = [UIFont systemFontOfSize:13];
[cellView addSubview:goingTimeStampLabel];
CGFloat x = 200;
CGFloat width = 55;
CGFloat height = [rowHeight floatValue];
CGFloat y = ([rowHeight floatValue] - height)/2;
UIButton *callButton = [[UIButton alloc] initWithFrame:CGRectMake(x, y, width, height)];
UIImage *callIcon = [UIImage imageNamed:#"call.png"];
[callButton setImage:callIcon forState:UIControlStateNormal];
[callButton addTarget:self
action:#selector(clickedCallButton:)
forControlEvents:UIControlEventTouchUpInside];
[cellView addSubview:callButton];
UIButton *textButton = [[UIButton alloc] initWithFrame:CGRectMake(x+width, y, width, height)];
UIImage *textIcon = [UIImage imageNamed:#"text.png"];
[textButton setImage:textIcon forState:UIControlStateNormal];
[textButton addTarget:self
action:#selector(clickedTextButton:)
forControlEvents:UIControlEventTouchUpInside];
[cellView addSubview:textButton];
return cellView;
}
SKSTableView.m
#import "SKSTableView.h"
#import "SKSTableViewCell.h"
#import "SKSTableViewCellIndicator.h"
#import <objc/runtime.h>
#pragma mark - NSArray (SKSTableView)
#interface NSMutableArray (SKSTableView)
- (void)initiateObjectsForCapacity:(NSInteger)numItems;
#end
#implementation NSMutableArray (SKSTableView)
- (void)initiateObjectsForCapacity:(NSInteger)numItems
{
for (NSInteger index = [self count]; index < numItems; index++) {
NSMutableArray *array = [NSMutableArray array];
[self addObject:array];
}
}
#end
#pragma mark - SKSTableView
#interface SKSTableView () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) NSMutableArray *expandedIndexPaths;
#property (nonatomic, strong) NSMutableDictionary *expandableCells;
#end
#implementation SKSTableView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_shouldExpandOnlyOneCell = NO;
}
return self;
}
- (void)setSKSTableViewDelegate:(id<SKSTableViewDelegate>)SKSTableViewDelegate
{
self.dataSource = self;
self.delegate = self;
[self setSeparatorColor:[UIColor colorWithRed:236.0/255.0 green:236.0/255.0 blue:236.0/255.0 alpha:1.0]];
if (SKSTableViewDelegate)
_SKSTableViewDelegate = SKSTableViewDelegate;
}
- (void)setSeparatorColor:(UIColor *)separatorColor
{
[super setSeparatorColor:separatorColor];
[SKSTableViewCellIndicator setIndicatorColor:separatorColor];
}
- (NSMutableArray *)expandedIndexPaths
{
if (!_expandedIndexPaths)
_expandedIndexPaths = [NSMutableArray array];
return _expandedIndexPaths;
}
- (NSMutableDictionary *)expandableCells
{
if (!_expandableCells)
_expandableCells = [NSMutableDictionary dictionary];
return _expandableCells;
}
#pragma mark - UITableViewDataSource
#pragma mark - Required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_SKSTableViewDelegate tableView:tableView numberOfRowsInSection:section] + [[[self expandedIndexPaths] objectAtIndex:section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (![self.expandedIndexPaths[indexPath.section] containsObject:indexPath]) {
NSIndexPath *tempIndexPath = [self correspondingIndexPathForRowAtIndexPath:indexPath];
SKSTableViewCell *cell = (SKSTableViewCell *)[_SKSTableViewDelegate tableView:tableView cellForRowAtIndexPath:tempIndexPath];
if ([[self.expandableCells allKeys] containsObject:tempIndexPath])
[cell setIsExpanded:[[self.expandableCells objectForKey:tempIndexPath] boolValue]];
[cell setSeparatorInset:UIEdgeInsetsZero];
if (cell.isExpandable) {
[self.expandableCells setObject:[NSNumber numberWithBool:[cell isExpanded]]
forKey:indexPath];
UIButton *expandableButton = (UIButton *)cell.accessoryView;
[expandableButton addTarget:tableView
action:#selector(expandableButtonTouched:event:)
forControlEvents:UIControlEventTouchUpInside];
if (cell.isExpanded) {
cell.accessoryView.transform = CGAffineTransformMakeRotation(M_PI);
} else {
if ([cell containsIndicatorView])
[cell removeIndicatorView];
}
} else {
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell removeIndicatorView];
cell.accessoryView = nil;
}
return cell;
} else {
NSIndexPath *indexPathForSubrow = [self correspondingIndexPathForSubRowAtIndexPath:indexPath];
UITableViewCell *cell = [_SKSTableViewDelegate tableView:(SKSTableView *)tableView cellForSubRowAtIndexPath:indexPathForSubrow];
cell.backgroundView = nil;
cell.backgroundColor = [self separatorColor];
cell.indentationLevel = 2;
return cell;
}
}
#pragma mark - Optional
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(numberOfSectionsInTableView:)]) {
NSInteger numberOfSections = [_SKSTableViewDelegate numberOfSectionsInTableView:tableView];
if ([self.expandedIndexPaths count] != numberOfSections)
[self.expandedIndexPaths initiateObjectsForCapacity:numberOfSections];
return numberOfSections;
}
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:titleForHeaderInSection:)])
return [_SKSTableViewDelegate tableView:tableView titleForHeaderInSection:section];
return nil;
}
#pragma mark - UITableViewDelegate
#pragma mark - Optional
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:didSelectRowAtIndexPath:)])
[_SKSTableViewDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:didDeselectRowAtIndexPath:)])
[_SKSTableViewDelegate tableView:tableView didDeselectRowAtIndexPath:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
SKSTableViewCell *cell = (SKSTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[SKSTableViewCell class]] && cell.isExpandable) {
cell.isExpanded = !cell.isExpanded;
NSIndexPath *_indexPath = indexPath;
if (cell.isExpanded && self.shouldExpandOnlyOneCell) {
_indexPath = [self correspondingIndexPathForRowAtIndexPath:indexPath];
[self collapseCurrentlyExpandedIndexPaths];
}
NSInteger numberOfSubRows = [self numberOfSubRowsAtIndexPath:_indexPath];
NSMutableArray *indexPaths = [NSMutableArray array];
NSInteger row = _indexPath.row;
NSInteger section = _indexPath.section;
for (NSInteger index = 1; index <= numberOfSubRows; index++) {
NSIndexPath *expIndexPath = [NSIndexPath indexPathForRow:row+index inSection:section];
[indexPaths addObject:expIndexPath];
}
if (cell.isExpanded) {
[self setIsExpanded:YES forCellAtIndexPath:_indexPath];
[self insertExpandedIndexPaths:indexPaths forSection:_indexPath.section];
} else {
[self setIsExpanded:NO forCellAtIndexPath:_indexPath];
[self removeExpandedIndexPaths:indexPaths forSection:_indexPath.section];
}
[self accessoryViewAnimationForCell:cell];
}
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:accessoryButtonTappedForRowWithIndexPath:)])
[_SKSTableViewDelegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
[self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = 0;
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:heightForHeaderInSection:)])
height = [_SKSTableViewDelegate tableView:tableView heightForHeaderInSection:section];
return height;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[UIView alloc] init];
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:viewForHeaderInSection:)])
view = [_SKSTableViewDelegate tableView:tableView viewForHeaderInSection:section];
return view;
}
#pragma mark - SKSTableViewUtils
- (IBAction)expandableButtonTouched:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self];
NSIndexPath *indexPath = [self indexPathForRowAtPoint:currentTouchPosition];
if (indexPath)
[self tableView:self accessoryButtonTappedForRowWithIndexPath:indexPath];
}
- (NSInteger)numberOfSubRowsAtIndexPath:(NSIndexPath *)indexPath
{
return [_SKSTableViewDelegate tableView:self numberOfSubRowsAtIndexPath:[self correspondingIndexPathForRowAtIndexPath:indexPath]];
}
- (NSIndexPath *)correspondingIndexPathForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index = 0;
NSInteger row = 0;
while (index < indexPath.row) {
NSIndexPath *tempIndexPath = [self correspondingIndexPathForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:indexPath.section]];
BOOL isExpanded = [[self.expandableCells allKeys] containsObject:tempIndexPath] ? [[self.expandableCells objectForKey:tempIndexPath] boolValue] : NO;
if (isExpanded) {
NSInteger numberOfExpandedRows = [_SKSTableViewDelegate tableView:self numberOfSubRowsAtIndexPath:tempIndexPath];
index += (numberOfExpandedRows + 1);
} else
index++;
row++;
}
return [NSIndexPath indexPathForRow:row inSection:indexPath.section];
}
- (NSIndexPath *)correspondingIndexPathForSubRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index = 0;
NSInteger row = 0;
NSInteger subrow = 0;
while (1) {
NSIndexPath *tempIndexPath = [self correspondingIndexPathForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:indexPath.section]];
BOOL isExpanded = [[self.expandableCells allKeys] containsObject:tempIndexPath] ? [[self.expandableCells objectForKey:tempIndexPath] boolValue] : NO;
if (isExpanded) {
NSInteger numberOfExpandedRows = [_SKSTableViewDelegate tableView:self numberOfSubRowsAtIndexPath:tempIndexPath];
if ((indexPath.row - index) <= numberOfExpandedRows) {
subrow = indexPath.row - index;
break;
}
index += (numberOfExpandedRows + 1);
} else
index++;
row++;
}
return [NSIndexPath indexPathForSubRow:subrow inRow:row inSection:indexPath.section];
}
- (void)setIsExpanded:(BOOL)isExpanded forCellAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *correspondingIndexPath = [self correspondingIndexPathForRowAtIndexPath:indexPath];
[self.expandableCells setObject:[NSNumber numberWithBool:isExpanded] forKey:correspondingIndexPath];
}
- (void)insertExpandedIndexPaths:(NSArray *)indexPaths forSection:(NSInteger)section
{
NSIndexPath *firstIndexPathToExpand = indexPaths[0];
NSIndexPath *firstIndexPathExpanded = nil;
if ([self.expandedIndexPaths[section] count] > 0) firstIndexPathExpanded = self.expandedIndexPaths[section][0];
__block NSMutableArray *array = [NSMutableArray array];
if (firstIndexPathExpanded && firstIndexPathToExpand.section == firstIndexPathExpanded.section && firstIndexPathToExpand.row < firstIndexPathExpanded.row) {
[self.expandedIndexPaths[section] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSIndexPath *updated = [NSIndexPath indexPathForRow:([obj row] + [indexPaths count])
inSection:[obj section]];
[array addObject:updated];
}];
[array addObjectsFromArray:indexPaths];
self.expandedIndexPaths[section] = array;
} else {
[self.expandedIndexPaths[section] addObjectsFromArray:indexPaths];
}
[self sortExpandedIndexPathsForSection:section];
// Reload TableView
[self insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}
- (void)removeExpandedIndexPaths:(NSArray *)indexPaths forSection:(NSInteger)section
{
NSUInteger index = [self.expandedIndexPaths[section] indexOfObject:indexPaths[0]];
[self.expandedIndexPaths[section] removeObjectsInArray:indexPaths];
if (index == 0) {
__block NSMutableArray *array = [NSMutableArray array];
[self.expandedIndexPaths[section] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSIndexPath *updated = [NSIndexPath indexPathForRow:([obj row] - [indexPaths count])
inSection:[obj section]];
[array addObject:updated];
}];
self.expandedIndexPaths[section] = array;
}
[self sortExpandedIndexPathsForSection:section];
// Reload Tableview
[self deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}
- (void)collapseCurrentlyExpandedIndexPaths
{
NSArray *expandedCells = [self.expandableCells allKeysForObject:[NSNumber numberWithBool:YES]];
if (expandedCells.count > 0) {
NSIndexPath *indexPath = [expandedCells firstObject];
[self.expandableCells setObject:[NSNumber numberWithBool:NO] forKey:indexPath];
[self removeExpandedIndexPaths:[self.expandedIndexPaths[indexPath.section] copy] forSection:indexPath.section];
SKSTableViewCell *cell = (SKSTableViewCell *)[self cellForRowAtIndexPath:indexPath];
cell.isExpanded = NO;
[self accessoryViewAnimationForCell:cell];
}
}
- (void)sortExpandedIndexPathsForSection:(NSInteger)section
{
[self.expandedIndexPaths[section] sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([obj1 section] < [obj2 section])
return (NSComparisonResult)NSOrderedAscending;
else if ([obj1 section] > [obj2 section])
return (NSComparisonResult)NSOrderedDescending;
else {
if ([obj1 row] < [obj2 row])
return (NSComparisonResult)NSOrderedAscending;
else
return (NSComparisonResult)NSOrderedDescending;
}
}];
}
- (void)accessoryViewAnimationForCell:(SKSTableViewCell *)cell
{
__block SKSTableViewCell *_cell = cell;
[UIView animateWithDuration:0.2 animations:^{
if (_cell.isExpanded) {
_cell.accessoryView.transform = CGAffineTransformMakeRotation(M_PI);
} else {
_cell.accessoryView.transform = CGAffineTransformMakeRotation(0);
}
} completion:^(BOOL finished) {
if (!_cell.isExpanded)
[_cell removeIndicatorView];
}];
}
#end
#pragma mark - NSIndexPath (SKSTableView)
static void *SubRowObjectKey;
#implementation NSIndexPath (SKSTableView)
#dynamic subRow;
- (NSInteger)subRow
{
id subRowObj = objc_getAssociatedObject(self, SubRowObjectKey);
return [subRowObj integerValue];
}
- (void)setSubRow:(NSInteger)subRow
{
id subRowObj = [NSNumber numberWithInteger:subRow];
objc_setAssociatedObject(self, SubRowObjectKey, subRowObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (NSIndexPath *)indexPathForSubRow:(NSInteger)subrow inRow:(NSInteger)row inSection:(NSInteger)section
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
indexPath.subRow = subrow;
return indexPath;
}
#end

Retain UITableView cell state when UISearchBar is used

I am using UISearchBar to search names in UITableView cells. How to retain the cell state when charachters are entered in UISearchBar?
I allocated the checkbox in cellForRowAtIndexPath and suppose I made the selection as shown in the screenshot below.
Now if I start searching with letter 'S', checkBox state is 'unchecked' as can be seen below.
How do I retain the checkBox state even if the cells are "filtered" while searching. I am aware that
cellForRowAtIndexPath is invoked every time when we enter text in UISearchBar.
Below is my cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *cellId = #"CheckBoxedCell";
NSString *cellId = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
CheckBoxedCellClass *cell = (CheckBoxedCellClass *)[self.tableViewContact dequeueReusableCellWithIdentifier:cellId];
if(!cell)
{
NSArray *nib;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass" owner:self options:nil];
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass_iPad" owner:self options:nil];
}
for (id object in nib)
{
if([object isKindOfClass:[CheckBoxedCellClass class]])
{
cell = (CheckBoxedCellClass *)object;
break;
}
}
cell = [nib objectAtIndex:0];
}
//handling check box
NSInteger rowNumber = 0;
for(NSInteger i = 0; i < indexPath.section ; i++)
{
rowNumber += [self tableView:self.tableViewContact numberOfRowsInSection:i];
}
rowNumber += indexPath.row;
SaveCheckBoxedView *saveContact;
if(isFiltered == YES)
{
saveContact = [filterdArray objectAtIndex:indexPath.row];
cell.nameLabel.text = saveContact.nameString;
cell.companyLabel.text = saveContact.companyString;
}
else
{
saveContact = [mutableArray objectAtIndex:indexPath.row];
cell.nameLabel.text = [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.companyLabel.text = [NSString stringWithFormat:#"%#", [companyArray objectAtIndex:rowNumber]];
}
cell.invIdLabel.text = [NSString stringWithFormat:#"%#", saveContact.invitId];
UIButton *checkBox;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(7, 8, 30, 30)];
}
else
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(15, 13, 30, 30)];
}
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
[checkBox addTarget:self action:#selector(checkBoxClicked:event:) forControlEvents:UIControlEventTouchUpInside];
// handle check box view reset when scrolled
if(isFiltered == YES)
{
NSLog(#"filtered");
checkBox.tag = indexPath.row;
BOOL buttonPressed = [[boolDict objectForKey:[NSString stringWithFormat:#"%d", indexPath.row]] boolValue];
NSLog(#"Row number = %d", indexPath.row);
[checkBox setSelected:buttonPressed];
if(buttonPressed)
{
[checkBox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
}
else
{
BOOL buttonPressed = [[boolDict objectForKey:[NSString stringWithFormat:#"%d", rowNumber]] boolValue];
NSLog(#"Row number = %d", rowNumber);
[checkBox setSelected:buttonPressed];
if(buttonPressed)
{
[checkBox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
checkBox.tag = rowNumber;
}
[cell.contentView addSubview:checkBox];
return cell;
}
-(void)checkBoxClicked:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableViewContact];
NSIndexPath *indexPath = [self.tableViewContact indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"value of indexPath.section %d ,indexPath.row %d",indexPath.section,indexPath.row);
UIButton *tappedButton = (UIButton*)sender;
NSLog(#"Tag number = %d", [sender tag]);
if([tappedButton.currentImage isEqual:[UIImage imageNamed:#"checkBox.png"]])
{
[sender setImage:[UIImage imageNamed: #"checkBoxMarked.png"] forState:UIControlStateNormal];
NSUserDefaults *buttonDefault = [NSUserDefaults standardUserDefaults];
[buttonDefault setBool:YES forKey:#"CHECKMARKEDKEY"];
[self.boolDict setObject:[NSNumber numberWithBool:YES] forKey:[NSString stringWithFormat:#"%d", [sender tag]]];
if(isFiltered == YES)
{
NSString *addId = [filteredArrayOfIds objectAtIndex:indexPath.row];
NSLog(#"filterd id = %#", addId); //get filtered array here
[arrayOfIds addObject:addId];
}
else
{
NSString *finalIntId = [mutableArrayOfIds objectAtIndex:tappedButton.tag];
NSLog(#"Tagged checked button id = %#", finalIntId);
[arrayOfIds addObject:finalIntId];
}
}
else
{
[sender setImage:[UIImage imageNamed:#"checkBox.png"]forState:UIControlStateNormal];
NSLog(#"UnChecked");
[self.boolDict setObject:[NSNumber numberWithBool:NO] forKey:[NSString stringWithFormat:#"%d", [sender tag]]];
if(isFiltered == YES)
{
[arrayOfIds removeObjectIdenticalTo:[filteredArrayOfIds objectAtIndex:tappedButton.tag]];
}
else
{
[arrayOfIds removeObjectIdenticalTo:[mutableArrayOfIds objectAtIndex:tappedButton.tag]];
}
}
}
And UISearhBar method is as follows
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
searchBar.text=#"";
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
[self.tableViewContact reloadData];
[self.tableViewContact scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if(searchText.length == 0)
{
isFiltered = NO;
}
else
{
isFiltered = YES;
filterdArray = [[NSMutableArray alloc] init];
filteredArrayOfIds = [[NSMutableArray alloc] init];
for (SaveCheckBoxedView *contact in mutableArray)
{
NSRange nameRange = [contact.nameString rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(nameRange.location != NSNotFound)
{
[filterdArray addObject:contact];
[filteredArrayOfIds addObject:contact.invitId];
}
}
}
[self.tableViewContact reloadData];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:NO animated:YES];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[self.mySearchBar resignFirstResponder];
[mySearchBar setShowsCancelButton:NO animated:YES];
}
- (void) searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
[tableViewContact registerClass:[CheckBoxedCellClass class] forCellReuseIdentifier:#"SaveContactCellID"];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[filterdArray removeAllObjects];
if(searchString.length > 0)
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.mySearchBar.text];
for (NSString *key in arrayOfCharacters)
{
NSArray *matches = [objectsForCharacters[key] filteredArrayUsingPredicate:predicate];
[filterdArray addObjectsFromArray:matches];
}
}
return YES;
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[self.tableViewContact reloadSectionIndexTitles];
}
Solved my own issue with the following code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *cellId = #"CheckBoxedCell";
NSString *cellId = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
CheckBoxedCellClass *cell = (CheckBoxedCellClass *)[self.tableViewContact dequeueReusableCellWithIdentifier:cellId];
if(!cell)
{
NSArray *nib;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass" owner:self options:nil];
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass_iPad" owner:self options:nil];
}
for (id object in nib)
{
if([object isKindOfClass:[CheckBoxedCellClass class]])
{
cell = (CheckBoxedCellClass *)object;
break;
}
}
cell = [nib objectAtIndex:0];
}
//set fonts
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
[cell.companyLabel setFont:[UIFont italicSystemFontOfSize:10.0]];
}
else
{
[cell.companyLabel setFont:[UIFont italicSystemFontOfSize:14.0]];
}
//handling check box
NSInteger rowNumber = 0;
for(NSInteger i = 0; i < indexPath.section ; i++)
{
rowNumber += [self tableView:self.tableViewContact numberOfRowsInSection:i];
}
rowNumber += indexPath.row;
SaveCheckBoxedView *saveContact;
if(isFiltered == YES)
{
saveContact = [filterdArray objectAtIndex:indexPath.row];
cell.nameLabel.text = saveContact.nameString;
cell.companyLabel.text = saveContact.companyString;
}
else
{
saveContact = [mutableArray objectAtIndex:indexPath.row];
cell.nameLabel.text = [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.companyLabel.text = [NSString stringWithFormat:#"%#", [companyArray objectAtIndex:rowNumber]];
}
cell.invIdLabel.text = [NSString stringWithFormat:#"%#", saveContact.invitId];
UIButton *checkBox;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(7, 8, 30, 30)];
}
else
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(15, 13, 30, 30)];
}
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
[checkBox addTarget:self action:#selector(checkBoxClicked:event:) forControlEvents:UIControlEventTouchUpInside];
// handle check box view reset when scrolled
if(isFiltered == YES)
{
NSLog(#"filtered");
BOOL buttonPress = [[boolDictForSearch objectForKey:[filteredArrayOfIds objectAtIndex:indexPath.row]] boolValue];
NSLog(#"button press = %d", buttonPress);
[checkBox setSelected:buttonPress];
if(buttonPress)
{
[checkBox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
checkBox.tag = indexPath.row;
}
else
{
BOOL buttonPressed = [[boolDict objectForKey:[NSString stringWithFormat:#"%d", rowNumber]] boolValue];
NSLog(#"button pressED = %d", buttonPressed);
NSLog(#"Row number = %d", rowNumber);
[checkBox setSelected:buttonPressed];
if(buttonPressed)
{
[checkBox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
checkBox.tag = rowNumber;
}
[cell.contentView addSubview:checkBox];
return cell;
}
-(void)checkBoxClicked:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableViewContact];
NSIndexPath *indexPath = [self.tableViewContact indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"value of indexPath.section %d ,indexPath.row %d",indexPath.section,indexPath.row);
UIButton *tappedButton = (UIButton*)sender;
NSLog(#"Tag number = %d", [sender tag]);
if([tappedButton.currentImage isEqual:[UIImage imageNamed:#"checkBox.png"]])
{
[sender setImage:[UIImage imageNamed: #"checkBoxMarked.png"] forState:UIControlStateNormal];
NSUserDefaults *buttonDefault = [NSUserDefaults standardUserDefaults];
[buttonDefault setBool:YES forKey:#"CHECKMARKEDKEY"];
[self.boolDict setObject:[NSNumber numberWithBool:YES] forKey:[NSString stringWithFormat:#"%d", [sender tag]]];
//[self.boolDictForSearch setObject:[NSNumber numberWithBool:YES] forKey:[NSString stringWithFormat:#"%#", saveContact.nameString]];
if(isFiltered == YES)
{
NSString *addId = [filteredArrayOfIds objectAtIndex:indexPath.row];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:YES] forKey:addId];
NSLog(#"filterd id = %#", addId); //get filtered array here
[arrayOfIds addObject:addId];
}
else
{
NSString *finalIntId = [mutableArrayOfIds objectAtIndex:tappedButton.tag];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:YES] forKey:finalIntId];
NSLog(#"Tagged checked button id = %#", finalIntId);
[arrayOfIds addObject:finalIntId];
}
}
else
{
[sender setImage:[UIImage imageNamed:#"checkBox.png"]forState:UIControlStateNormal];
NSLog(#"UnChecked");
[self.boolDict setObject:[NSNumber numberWithBool:NO] forKey:[NSString stringWithFormat:#"%d", [sender tag]]];
//[self.boolDictForSearch setObject:[NSNumber numberWithBool:NO] forKey:[NSString stringWithFormat:#"%#", saveContact.nameString]];
if(isFiltered == YES)
{
[arrayOfIds removeObjectIdenticalTo:[filteredArrayOfIds objectAtIndex:tappedButton.tag]];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:NO] forKey:[filteredArrayOfIds objectAtIndex:tappedButton.tag]];
}
else
{
[arrayOfIds removeObjectIdenticalTo:[mutableArrayOfIds objectAtIndex:tappedButton.tag]];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:NO] forKey:[mutableArrayOfIds objectAtIndex:tappedButton.tag]];
}
}
}

Resources