I'm developing an iOS application with latest SDK.
I have a UITableView with a custom UITableViewCell:
#interface FavouriteCell : UITableViewCell
#property (unsafe_unretained, nonatomic) IBOutlet UIImageView *selectIcon;
#property (unsafe_unretained, nonatomic) IBOutlet UILabel *favName;
#property (nonatomic) BOOL checked;
+ (NSString *)reuseIdentifier;
#end
On selectIcon I set two images from normal and highlighted. When I do cell.checked = !selected; on tableView:didSelectRowAtIndexPath: it works perfectly.
But when I try to reset every selected cell on clearSelectedFavourites:, it doesn't work.
#interface FavViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate, UIAlertViewDelegate>
{
#private
NSMutableArray* _favsSelected;
BOOL* _isOnEditingMode;
}
// ######### FavViewController implementation ##############
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.title = NSLocalizedString(#"Favoritos", #"Favoritos");
self.tabBarItem.image = [UIImage imageNamed:#"fav"];
_favsSelected = [[NSMutableArray alloc] init];
_isOnEditingMode = NO;
}
return self;
}
- (UITableViewCell* )tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellForRowAtIndexPath");
static NSString* CellIdentifier = #"FavCell";
FavouriteCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"FavouriteCell" owner:self options:nil];
cell = _favCell;
self.favCell = nil;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.favName.font = [UIFont systemFontOfSize:15.0f];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
#pragma mark - UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath: %#", indexPath);
if (tableView.isEditing)
{
BOOL selected = NO;
if ((_favsSelected != nil) && ([_favsSelected count] > 0))
selected = ([_favsSelected indexOfObject:indexPath] != NSNotFound);
FavouriteCell* cell =
(FavouriteCell*)[tableView cellForRowAtIndexPath:indexPath];
NSLog(cell.checked ? #"Yes" : #"No");
cell.checked = !selected;
if (selected)
[_favsSelected removeObject:indexPath];
else
[_favsSelected addObject:indexPath];
}
}
- (IBAction)editFavList:(id)sender
{
NSLog(#"edit button clicked!");
if ([_favList isEditing])
{
[self clearSelectedFavourites];
[_favList setEditing:NO animated:YES];
[_editButton setImage:[UIImage imageNamed:#"ButtonEdit.png"] forState:UIControlStateNormal];
}
else
{
[_favList setEditing:YES animated:YES];
[_editButton setImage:[UIImage imageNamed:#"done_button.png"] forState:UIControlStateNormal];
}
}
- (void)clearSelectedFavourites
{
for(int index = 0; index < [_favsSelected count]; index++)
{
NSIndexPath* indexPath = (NSIndexPath*)[_favsSelected objectAtIndex:index];
FavouriteCell* cell = (FavouriteCell*)[self tableView:_favList cellForRowAtIndexPath:indexPath];
cell.checked = NO;
}
[_favsSelected removeAllObjects];
}
- (void)configureCell:(FavouriteCell *)cell
atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = nil;
object = [self.favListFetchedResultsController objectAtIndexPath:indexPath];
cell.favName.text = [[object valueForKey:#"name"] description];
}
Do you know why?
I have tried to set selectIcon to not hightlighted manually, but it doesn't work, and that code if the latest test I did.
I have also tested this: [cell setHighlighted:NO]; on clearSelectedFavourites: and it doesn't work.
You are not showing us your custom [self configureCell:cell atIndexPath:indexPath]; function, so I cannot know what's going on.
However a few things first:
The cells on the TableView are being reused.
So you cell select state needs to be set every time for each cell.
Also on your clearSelectedFavourites function, you are getting a reference to all selected cells, then clear their selection, which is pointless, because the cells are going to be reused.
You only need to loop through the visible UITableView cells and change their selection status, then clear your _favsSelected array...
- (void)clearSelectedFavourites
{
NSArray *cells = [self.tableView visibleCells];
for (FavouriteCell *cell in cells)
{
cell.checked = NO;
//might not be needed, or might be needed
[cell setNeedsDisplay];
}
[_favsSelected removeAllObjects];
}
Finally on your configureCell function, you should check if the cell should be checked or not, based on your _favsSelected array entries and just select it or not.
Edit
In your configureCell function you should check if the cell needs to be checked or not:
- (void)configureCell:(FavouriteCell *)cell
atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = nil;
object = [self.favListFetchedResultsController objectAtIndexPath:indexPath];
cell.favName.text = [[object valueForKey:#"name"] description];
cell.checked = [_favsSelected containsObject:indexPath];
}
You can do like this :
[tbl beginUpdates];
/* call you method with animation */
[tbl endUpdates];
[tbl reloadData];
Related
I have an issue regarding height of custom cell. I need to increase the height of cell when one button on cell was clicked. her I know to use two methods (heightforrow and didselectrow) for it but I am confuse that when I clicked on button that time custom method for button action is called and I am using those two methods in controller.I attached my code:
in customcell.m
- (IBAction)btnRestPlusClicked:(id)sender
{
UIButton *btn = (id)sender;
btn.selected =!btn.selected;
if (btn.selected)
{
NSLog(#"selected");
// _viewExtraScheduleAmount.hidden = FALSE;//I need to make this event on button action and same time increase the height of cell.
}
else
{
btn.tag = 0;
// _viewExtraScheduleAmount.hidden = TRUE;
}
now I need that when button clicked that time only that row's height will increase.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//if (ceel.btnRestPlusClicked.selected)
//{
// return 100;
// }
// return 60;
I know I am wrong here but how to use this method?
}
Please can any one help me out from this?
Thanks
Create NSMutableDictionary inside of UIViewController where you will store NSIndexPath of btnRestPlusClicked cells.
Then track when button plus selected in each cell:
In CustomCell.h
#protocol CustomCellDelegate;
#interface CustomCell : UITableViewCell
#property (nonatomic, weak) id<CustomCellDelegate> delegate;
#end
#protocol CustomCellDelegate <NSObject>
- (void)customCellButtonPlusSelected:(CustomCell*)cell;
#end
In CustomCell.m
- (IBAction)btnRestPlusClicked:(id)sender
{
[self.delegate customCellButtonPlusSelected:self];
}
In UIViewController when you create cell for cellForRowAtIndexPath add:
cell.delegate = self
and conform UIViewController to CustomCellDelegate
-(void)customCellButtonPlusSelected:(CustomCell*)cell {
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSString *key = [NSString stringWithFormat:#"%li:%li", indexPath.section, indexPath.row];
[buttonPlusClickedDictionary setObject:#"1" forKey:key];
[self.tableView reloadRowsAtIndexPaths:#[indexPath]];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *key = [NSString stringWithFormat:#"%li:%li", indexPath.section, indexPath.row];
if ([buttonPlusClickedDictionary objectForKey:key]) {
return 100;
}
return 60;
}
Try adding a boolean variable as class member. Set it when you click the button.
Reload the table view at the end of - (IBAction)btnRestPlusClicked:(id)sender
In - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath change the height of tableview cell if boolean variable is set.
The problem is not the implementation of heightForRowAtIndexPath: but in getting the runtime to call heightForRowAtIndexPath: again, so that it can discover that your cell height has changed. To do that, your button should tell the table view to reloadData.
You can change the height of your selected cell when you tap on that cell button like
ViewController.h
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
IBOutlet UITableView *myTableView;
}
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController {
NSArray *tableData;
int currentselection;
int cellno;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
currentselection = -1;
tableData = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee", #"White Chocolate Donut", #"Starbucks Coffee", nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
- (CGFloat)tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath {
int rowHeight;
if ([indexPath row] == currentselection) {
rowHeight = 200;
} else {
rowHeight = 50;
}
return rowHeight;
}
- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"SimpleTableItem";
NSInteger myInteger = indexPath.row;
cellno = (int) myInteger;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
// add custom expand height button
UIButton *addFriendButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
addFriendButton.frame = CGRectMake(200.0f, 5.0f, 75.0f, 30.0f);
[addFriendButton setTitle:#"Add" forState:UIControlStateNormal];
[cell addSubview:addFriendButton];
[addFriendButton addTarget:self action:#selector(addHeight:) forControlEvents:UIControlEventTouchUpInside];
[addFriendButton setTag:cellno];
return cell;
}
- (IBAction) addHeight:(UIButton *)sender {
NSInteger myInteger = sender.tag;
currentselection = (int) myInteger;
[myTableView beginUpdates];
[myTableView endUpdates];
}
I want to make paging swipe left and right using UIScrollView after view detailController.
First, main.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
OZDetailViewController *detailViewController = [[OZDetailViewController alloc] initWithNibName:#"OZDetailViewController" bundle:nil];
detailViewController.arrDetailNews = [_arrNews objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
OZDetailViewController *arrNewsAll = [[OZDetailViewController alloc] initWithNibName:#"OZDetailViewController" bundle:nil];
arrNewsAll.allNewsArray = _arrNews;
[self.navigationController pushViewController:arrNewsAll animated:YES];
}
When I selected content in tableviewcell, arrDetailNews can loaded in method viewDidLoad() and cellForRowAtIndexPath(). But arrNewsAll cannot loaded in method cellForRowAtIndexPath().
This is my detailViewController.h:
#property (nonatomic, copy) NSArray *allNewsArray;
And detailViewCOntroller.m:
#synthesize allNewsArray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.separatorColor = [UIColor clearColor];
NSLog(#"dataArray: %#", allNewsArray);
}
- (int)numberINSectionsInTableView: (UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 4;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"dataArrayCell: %#", allNewsArray);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"New Cell"];
}
if(indexPath.row != self.arrDetailNews.count-1){
UIImageView *line = [[UIImageView alloc] initWithFrame:CGRectMake(0, 44, 320, 2)];
line.backgroundColor = [UIColor whiteColor];
[cell addSubview:line];
}
tableView.allowsSelection = NO;
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
if (indexPath.row==0) {
cell.textLabel.text = #"1st";
}
if (indexPath.row==1) {
cell.textLabel.text = #"2nd";
}
if (indexPath.row==2) {
cell.textLabel.text = #"3rd";
}
return cell;
}
If allNewsArray can loaded in cellForRowAtIndexPath() I can continue next step for paging with UIScrollView. Note, numberOfRowsInSection I set to 4 because I need 4 rows (custom view).
Assuming you setup your delegate & dataSource outlets correctly from xib/storyboard, you still need to specify the number of rows per section (or number of sections).
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return allNewsArray.count;
}
Alternatively, the method for number of sections is:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
I'm developing an app with a news feed.
This is a PFQueryTableView loading content from parse.com.
I also have a detail ViewController attached with a segue.
My question is:
How can I show that there is a cell that hasn't been clicked before?
Like in the Mail application in IOS.
Here's a picture:
http://i.stack.imgur.com/vO2N3.png
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"Nyhet";
// The key of the PFObject to display in the label of the default cell style
self.textKey = #"Rubrik";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 10;
}
return self;
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleDefault;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Change button color
sidebarButton.tintColor = [UIColor whiteColor];
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
sidebarButton.target = self.revealViewController;
sidebarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
/* if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}*/
[query orderByDescending:#"Prioritering"];
return query;
}
// Override to customize the look of a cell representing an object. The default is to display
// a UITableViewCellStyleDefault style cell with the label being the first key in the object.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"Rubrik"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"Detaljer"];
return cell;
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(#"error: %#", [error localizedDescription]);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [object objectForKey:#"Rubrik"];
recipe.prepTime = [object objectForKey:#"Text"];
recipe.detaljer = [object objectForKey:#"Detaljer"];
recipe.rubriker = [object objectForKey:#"Rubrik"];
destViewController.recipe = recipe;
}
}
#end
I think it's better use custom UITableViewCell example:
CustomTableViewCell.h
#interface CustomTableViewCell : UITableViewCell
#property(assign) bool beforeClicked
#end
CustomTableViewCell.m
#import CustomTableViewCell.h
#implementation CustomTableViewCell
#synthesize beforeClicked;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
#end
And, example:
CustomTableViewCell.h //add this header
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = (CustomTableViewCell *)[[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"Rubrik"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"Detaljer"];
cell.beforeClicked = NO;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *myCell = [tableView cellForRowAtIndexPath:indexPath];
myCell.beforeClicked = YES;
}
Two solutions come to mind.
The simpler solution would be using an NSMutableArray to hold all visited cells. In didSelectRowAtIndexPath: do this :
if (![visitedCellsArray containsObject:[NSNumber numberWithInt:indexPath.row]])
[visitedCellsArray addObject:[NSNumber numberWithInt:indexPath.row]];
Then set a backgroundColor to your cell (just a suggestion, you may use any UI indicator - dot, color, etc) in your cellForRowAtIndexPath:
Second, might not be conducive to your purpose. I don't really know if the dictionary you are using is mutable or not, and whether adding keys will have any effect on your flow of control. But If adding a key is possible, add a key like #"seen" and set it with [NSNumber numberWithBool:YES] in didSelectRowAtIndexPath:, and in cellForRowAtIndexPath: add appropriate UI indication based on the value of this key. This method is better memory wise.
I'd give your PFReceipt objects a property BOOL new.
Then just get and set that property and in cellForRow you set the font based on the vale of the property.
clean and even persistent.
...
so to reiterate:
modify PFReceipt object to have a property new
modify - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
...
cell.clickedBefore = !receipe.new;
mark receipes as no longer new when shown
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
...
PFObject *object = [self.objects objectAtIndex:indexPath.row];
selectedCell.clickedBefore = !object.new;
None of the solutions provided take into account that there may be more than one user of the app. If you store a "read" or "new" property in the object, this will only show if ANYBODY has read it. So if Jane reads it, Mark will see it as read.
To handle this separately for all users, you need another parse class to handle reading status. This gets a little complex to implement, but it is the only way to solve it all on the server.
Another option would be to store a read status list on every client. This means some kind of local persistent store that knows what recipes are read, and compare this to the data fetched from Parse.
i wanted to make collapsable/expandable tableview in which i have two headers product and services and each of them contains 10+ object with custom cell which contains checkmark on left side and label. i check for the tutorials but most of them are using .xib while my project is based on storyboard.
i check these tutorials, can anyone please help me regarding this.
https://www.cocoacontrols.com/controls/collapseclick
https://www.cocoacontrols.com/controls/ratreeview
https://www.cocoacontrols.com/controls/combobox-for-uitableview
I have found a great sample project on this at:
https://github.com/singhson/Expandable-Collapsable-TableView
It is very easy to understand and implement.
//
// ViewController.h
// expandableTV
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
NSMutableIndexSet *expandedSections;
}
#property (weak, nonatomic) IBOutlet UITableView *tbl_expandablecategory;
#end
//
// ViewController.m
// expandableTV
//
#import "ViewController.h"
#import "expandableTC.h"`
#interface ViewController ()
{
NSArray *jsonArray;
BOOL currentlyExpanded;
}
#end
#implementation ViewController
#synthesize tbl_expandablecategory;
NSMutableArray *arr_categorymenumodel;
- (void)viewDidLoad {
[super viewDidLoad];
arr_categorymenumodel=[[NSMutableArray alloc] init];
if (!expandedSections)
{
expandedSections = [[NSMutableIndexSet alloc] init];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 6;//[arr_categorymenumodel count];
}
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self tableView:tableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return 2;
}
}
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row==0)
{
return 40;
}
return 270;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell...
if (!indexPath.row)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =#"Room ";// [NSString stringWithFormat:#"%#",[[arr_categorymenumodel objectAtIndex:indexPath.section] valueForKey:#"CategoryName"]];
// cell.backgroundColor=[UIColor colorWithRed:237.0/255.0 green:237.0/255.0 blue:237.0/255.0 alpha:1.0];
cell.textLabel.font=[UIFont fontWithName:#"HelveticaNeue" size:20.0];
if (currentlyExpanded)
{
}
cell.accessoryView = [[UIImageView alloc]initWithImage: [UIImage imageNamed:#"rightarrow.png"]];
return cell;
}
else
{
expandableTC *cell = [tableView dequeueReusableCellWithIdentifier:#"Customcell"];
return cell;
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
cell.accessoryView = [[UIImageView alloc]initWithImage: [UIImage imageNamed:#"rightarrow.png"]];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
cell.accessoryView = [[UIImageView alloc]initWithImage: [UIImage imageNamed:#"downarrow.png"]];
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
[tmpArray addObject:tmpIndexPath];
}
if (currentlyExpanded)
{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationFade];
}
else
{
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationFade];
}
}
}
}
#end
So basically I am getting the wrong data on every textField by scrolling my TableView (Everything is mixed up). I know, this is because the awesome optimization of the reusable cells in the UITableView, so the indexpath are changing constantly, but still I don't know how to solve this.
Having an UILabel in the same cell I solved this problem by adding a specific tag in every label view, so the tableview knows which data is going to return on a view but for some reason this is not possible for my textfield view.
Here is my code:
#define DESCRIPTION_TAG 10
#define TEXTFIELD_TAG 11
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Description Cell";
// Intatiating my own TableViewCell
CustomLocationCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell){
cell = [[CustomLocationCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.rowText = (UILabel *) [cell viewWithTag:DESCRIPTION_TAG]; // returning view with unique tag
cell.rowTextField = (UITextField *)[cell viewWithTag:TEXTFIELD_TAG]; // NOT WORKING!!! Data get mix up
cell.rowTextField.delegate = cell; // sending the delegate to custom class cell
cell.delegate = self; // make connection with my #protocol
switch (indexPath.section) {
case 0:
cell.rowText.text = [self.descriptions objectAtIndex:indexPath.row];
cell.rowTextField.placeholder = [self.descriptionsPlaceholder objectAtIndex:indexPath.row];
break;
case 1:
cell.rowText.text = [self.rooms objectAtIndex:indexPath.row];
cell.rowTextField.placeholder = [self.contentPlaceholder objectAtIndex:indexPath.row];
break;
default:
break;
}
return cell;
}
Any help is appreciated.
Here is an update of my data source:
On my CustomTableViewCell I do have outlets for my UILabel and UITextfield
// UITableView DataSource
- (NSArray *)sections
{
if (!_sections){
_sections = [[NSArray alloc] initWithObjects:#"First Description", #"Second Descriptions", nil];
}
return _sections;
}
- (NSMutableArray *)rooms
{
if (!_rooms){
_rooms = [[NSMutableArray alloc] init];
}
return _rooms;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.sections.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0:
return [self.descriptions count];
break;
case 1:
return [self.rooms count];
break;
default:
break;
}
return 0;
}
I'm not sure exactly what you're trying to accomplish, but here's an example that works with labels and text fields with placeholder text. You'll notice that in cellForRowAtIndexPath, I set both the text and placeholder to nil, so that when a cell is reused, it doesn't have the wrong text in it. Also, when doing the text fields, I check if the array has placeholder text at that index, and if so, I reset the placeholder, and if not I reset the text.
In order for the text field delegate methods to work properly, each text filed needs a unique tag (not just one tag for labels and another for text fields) that I set equal to (indexPath.row + 1000*indexPath.section).
#import "TableController.h"
#import "CustomLocationCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *descriptions;
#property (strong,nonatomic) NSMutableArray *descriptionsPlaceholder;
#property (strong,nonatomic) NSArray *rooms;
#property (strong,nonatomic) NSMutableArray *contentPlaceholder;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
self.descriptions = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight"];
self.descriptionsPlaceholder = [#[#"Placeholder1",#"Placeholder2",#"Placeholder3",#"Placeholder4",#"Placeholder5",#"Placeholder6",#"Placeholder7",#"Placeholder8"] mutableCopy];
self.rooms = #[#"Room1", #"Room2", #"Room3", #"Room4",#"Room5", #"Room6", #"Room7", #"Room8"];
self.contentPlaceholder = [#[#"ContentPH1",#"ContentPH2",#"ContentPH3",#"ContentPH4",#"ContentPH5",#"ContentPH6",#"ContentPH7",#"ContentPH8"] mutableCopy];
[self.tableView reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.descriptions.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Description Cell";
CustomLocationCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.rowTextField.delegate = self;
cell.rowTextField.tag = indexPath.row + 1000*indexPath.section;
cell.rowTextField.placeholder = nil;
cell.rowTextField.text = nil;
switch (indexPath.section) {
case 0:
cell.rowText.text = [self.descriptions objectAtIndex:indexPath.row];
if ([self.descriptionsPlaceholder[indexPath.row] hasPrefix:#"Placeholder"]) {
cell.rowTextField.placeholder = [self.descriptionsPlaceholder objectAtIndex:indexPath.row];
}else{
cell.rowTextField.text = [self.descriptionsPlaceholder objectAtIndex:indexPath.row];
}
break;
case 1:
cell.rowText.text = [self.rooms objectAtIndex:indexPath.row];
if ([self.contentPlaceholder[indexPath.row] hasPrefix:#"ContentPH"]) {
cell.rowTextField.placeholder = [self.contentPlaceholder objectAtIndex:indexPath.row];
}else{
cell.rowTextField.text = [self.contentPlaceholder objectAtIndex:indexPath.row];
}
break;
default:
break;
}
return cell;
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.tag >= 1000 && ![textField.text isEqualToString: #""]) {
[self.contentPlaceholder replaceObjectAtIndex:textField.tag - 1000 withObject:textField.text];
}else if (textField.tag < 1000 && ![textField.text isEqualToString: #""]) {
[self.descriptionsPlaceholder replaceObjectAtIndex:textField.tag withObject:textField.text];
}
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}