I'm trying to create and draw a UITableView populated by an array. I've created a UIViewController and set the UIViewController as my tableview's delegate. However, it seems that my cellForRowAtIndexPath method is not called when the tableview is created, so my table never gets populated. What am I missing here? (All labels are initialized in that function, as I'm just trying to create a Main Menu using a table, all entries will be fixed).
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
prefTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480) style:UITableViewStylePlain];
[prefTable setDelegate:self];
//NSIndexSet *tmpIndRange = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0,1)];
//[prefTable insertSections:tmpIndRange withRowAnimation:UITableViewRowAnimationNone];
//[tmpIndRange release];
labelArray = [[NSMutableArray alloc] initWithCapacity:10];
[labelArray addObject:NSLocalizedString(#"Account ID",#"C_ACC_ID")];
[labelArray addObject:NSLocalizedString(#"Site ID",#"Site_ID")];
[labelArray addObject:NSLocalizedString(#"Station ID",#"Station_ID")];
[labelArray addObject:NSLocalizedString(#"Encryption Key",#"ENC_KEY")];
[labelArray addObject:NSLocalizedString(#"Encryption On",#"ENC_ON")];
placeholderArray = [[NSMutableArray alloc] initWithCapacity:10];
[labelArray addObject:NSLocalizedString(#"Required",#"Required")];
[labelArray addObject:NSLocalizedString(#"Required",#"Required")];
[labelArray addObject:NSLocalizedString(#"Required",#"Required")];
[labelArray addObject:NSLocalizedString(#"Required",#"Required")];
[labelArray addObject:NSLocalizedString(#"Required",#"Required")];
self.view = prefTable;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
NSInteger currenttag = textField.tag;
NSLog(#"%d",textField.tag);
//accountId = textField.text;
//stationId = textField.text;
//siteId = textField.text;
[textField resignFirstResponder];
return YES;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
[cell setAccessoryType:UITableViewCellAccessoryNone];
[cell.textLabel setText:[labelArray objectAtIndex:indexPath.row]];
//((TextInputTableCell *)cell).textField.placeholder = [placeholderArray objectAtIndex:indexPath.row];
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 4;
}
Also, will it be better if I assigned the menu items using a data source? It seems that section headers can only be assigned using a data source. Thanks!
tableView:cellForRowAtIndexPath: is part of the UITableViewDataSource protocol - not UITableViewDelegate. You'll need to make your controller the datasource of the UITableView:
prefTable.dataSource = self;
Related
I did XML parsing for the content I obtained from WCF Service. I loaded the data in NSMutableArray using NSXMLParser.Now I want that data to be loaded in tableview in a UIView. But I can see the empty tableview being loaded and data doesn't. Couldn't understand where I am going wrong.
My NSMutableArray is like this:
(
{
UserName="Roy";
Password="126";
},
{
UserName="Joy";
Password="123";
},
{
UserName="Rony";
Password="5983";
}
-------------
-------------
)
And the code for UItableView is :
#interface RootViewController : UIViewController<NSXMLParserDelegate,UITableViewDataSource,UITableViewDelegate>
{
NSMutableArray *arr;
UITableView *tableView;
}
- (void)viewDidLoad
{
UITableView* tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:tableView];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arr count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
}
NSString *tempstring=[arr objectAtIndex:indexPath.row];
cell.textLabel.text= tempstring;
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
I am getting empty tableview with some empty rows. How can i fix this?
hey you just add this code in your cellForRowAtIndexPath delegete:-
EDITED
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
}
SMutableDictionary *d = (NSMutableDictionary *) [arr objectAtIndex:indexPath.row]
UILabel *username = [[UILabel alloc]initWithFrame:CGRectMake(10, 5, 280, 30)];
username.textColor =DARK_VIEW;
username.font=[UIFont boldSystemFontOfSize:15];
[username setTextAlignment:UITextAlignmentLeft];
[username setText:[d valueForKey:#"UserName"]];
[cell addSubview:username];
[username release];
UILabel *Password = [[UILabel alloc]initWithFrame:CGRectMake(11, 25, 280, 30)];
Password.textColor =DARK_VIEW;
Password.font=[UIFont fontWithName:#"arial" size:12];
[Password setTextAlignment:UITextAlignmentLeft];
[Password setText:[d valueForKey:#"Password"]];
[cell addSubview:Password];
[Password release];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SMutableDictionary *d = (NSMutableDictionary *) [arr objectAtIndex:indexPath.row]
NSString *forNExtViewString =[d valueForKey:#"EmployeID"];
objSectonView =[[cntrSecodviewcontroller alloc]initWithNibName:#"cntrSecodviewcontroller" bundle:nil];
[self.navigationController pushViewController:objSectonView animated:YES];
}
You forgot to set the tableView delegate and datasource. Your datasource also looks like it contains a collection of NSDictionaries. In your cellForRow you have to correctly extract the values from the dictionary
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView* tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
Like Nitin Gohel pointed out
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
}
cell.textLabel.text = [[arr objectAtIndex:indexPath.row] valueForKey:#"UserName"];
return cell;
}
Just make sure about the following things :
Values are retained in the array
Reload your TableView after the objects are added to array.
i.e [tableView reloadData];
And Just replace your method with this one.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
}
//Over here just print the value of your array , to cross check whether the values are retained in the Array
NSLog(#"%#",[arr objectAtIndex:indexPath.row]);
NSString *tempstring= [[arr objectAtIndex:indexPath.row] valueForKey:#"UserName"];
cell.textLabel.text= tempstring;
return cell;
}
This would definitely bring the solution of your problem.
Check this and confirm your delegates, that might be the reason of not getting tableview called.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
tablView = [[UITableView alloc]initWithFrame:CGRectMake(10, 10, 300, 460)];
tablView.delegate = self;
tablView.dataSource = self;
[self.view addSubview:tablView];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell * cell = [tablView
dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
UILabel *lbl5 = [[UILabel alloc]initWithFrame:CGRectMake(30, 5, 250, 50);];
UILabel *lbl6 = [[UILabel alloc]initWithFrame:CGRectMake(30, 60, 250, 50)];
lbl1.text = [arrayName objectAtIndex:i];
lbl2.text = [arrayAddress objectAtIndex:i];
NSString *tempstring=[arr1 objectAtIndex:indexPath.row];
NSString *tempstring=[arr2 objectAtIndex:indexPath.row];
[cell addSubview:lbl1];
[cell addSubview:lbl2];
// cell.textLabel.text= tempstring;
return cell;
}
You are accessing array at indexPath, and this array contain dictionary, so first get array and take it in dictionary and access it with key value
cell.textLabel.text = [[arr objectAtIndex:indexPath.row] objectForKey:#"UserName"];
Your mutable array has elements of dictionary type. so while updating the text in table cell try to grab dictionary from array based on your indexPath.row and then objectForKey: for whichever key you want to use. see code below
you should try to use
cell.textLabel.text = [[yourMutableArr objectAtIndex:indexPath.row] valueForKey:#"UserName"];
cell.detailTextLabel.text = [[yourMutableArr objectAtIndex:indexPath.row] valueForKey:#"Password"];
and you can use the default separater of table cells.
I have two array and three button in segment control i want that when i load screen by default it get result Array items in table view and then on click on tomorrows button it get nextArray value and show in table
-(void)viewDidLoad{
if(!resultArray){
resultArray =[[NSMutableArray alloc] init];
}
[self setUpData];
if(!nextArray){
nextArray =[[NSMutableArray alloc] init];
}
[self nextData];
appointmentsOfDay = [[NSMutableArray alloc] arrayWithArray:resultArray copyItems:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [appointmentsOfDay count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel * dobLabel = nil;
static NSString * Identifier = #"Identifier";
UITableViewCell * cell = [table dequeueReusableCellWithIdentifier:Identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Identifier] autorelease];
dobLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 6, 100, 32)];
dobLabel.font = [UIFont systemFontOfSize:15];
dobLabel.tag = 999;
[cell addSubview:dobLabel];
[dobLabel release];
}
else {
dobLabel = (UILabel *)[cell viewWithTag:999];
}
appDelegate = (EMRAppDelegate *)[[UIApplication sharedApplication] delegate];
ObjectData *theCellData = [appointmentOfDay objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:15];
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.textLabel.text=[NSString stringWithFormat:#"%# %#",theCellData.firstName,theCellData.lasttName];
dobLabel.text = theCellData.appointmentTime;
return cell;
}
- (void)onDayButtonClick:(id)sender
{
UISegmentedControl * segmentedControl = (UISegmentedControl *)sender;
[appointmentsOfDay removeAllObjects];
if (segmentedControl.selectedSegmentIndex == 0) {
[appointmentsOfDay removeAllObjects];
appointmentsOfDay = [[NSMutableArray alloc] arrayWithArray:resultArray copyItems:YES];
}
else if (segmentedControl.selectedSegmentIndex == 1) {
[appointmentsOfDay addObject:nextArray];
}
else if (segmentedControl.selectedSegmentIndex == 2) {
}
[table reloadData];
}
Crash Report
EMR[1161:10703] -[__NSPlaceholderArray arrayWithArray:copyItems:]: unrecognized selector sent to instance 0x7320120
2012-04-09 14:13:35.021 EMR[1161:10703] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSPlaceholderArray arrayWithArray:copyItems:]: unrecognized selector sent to instance 0x7320120'
*** First throw call stack:
(0x201d052 0x2d01d0a 0x201eced 0x1f83f00 0x1f83ce2 0xc7a7 0x6bc64e 0x6bc941 0x6ce47d 0x6ce66f 0x6ce93b 0x6cf3df 0x6cf986 0x6cf5a4 0x9660 0x201eec9 0x5f95c2 0x5f955a 0x69eb76 0x69f03f 0x69e2fe 0x61ea30 0x61ec56 0x605384 0x5f8aa9 0x2f72fa9 0x1ff11c5 0x1f56022 0x1f5490a 0x1f53db4 0x1f53ccb 0x2f71879 0x2f7193e 0x5f6a9b 0x25bd 0x2535)
terminate called throwing an exception(lldb)
The problem is that you are allocation appointmentsOfDay everytime, So remove the following code,
appointmentsOfDay = [[NSMutableArray alloc] arrayWithArray:resultArray copyItems:YES];
and add it to viewdidload.
Then,
if (segmentedControl.selectedSegmentIndex == 0) {
[appointmentsOfDay addObject:resultArray];
}
else if (segmentedControl.selectedSegmentIndex == 1) {
[appointmentsOfDay addObject:nextArray];
}
Following code is implementing and may solve your problems
In this i implementing the two array when pressing the button then the another array fill int the Uitable.
In view did load method implement following code
- (void)viewDidLoad
{
[super viewDidLoad];
self.arOne=[NSArray arrayWithObjects:#"1",#"a",#"b",#"c",#"d",#"e", nil];
self.arTwo=[NSArray arrayWithObjects:#"x",#"y",#"z",#"o",#"p", nil];
[self.tableView reloadData];
}
In cellForRowAtIndexPath method implement following code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text=[(self.btnTapped.selected)?self.arTwo:self.arOne objectAtIndex:indexPath.row];
return cell;
}
IBAction method for connection between control and method
- (IBAction)btnTitle:(id)sender {
self.btnTapped.selected=!self.btnTapped.selected;
[self.tableView reloadData];
}
May this helping to solve your problem
This is the method that I prefer to use. Have a reference to your segmented control. Declare a read only property
#property (nonatomic, readonly) NSArray *appointmentOfDay;
and implement it as
-(NSArray*) appointmentOfDay {
NSArray *tData;
if (self.segmentedControl.value==0) {
//instantiate tData based on value
}
// do for all segmented control value
return tData;
}
And just call reloadData when Day button is clicked.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"celluleConnecte";
celluleConnecte *cell = (celluleConnecte *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
UIViewController *vue = [[UIViewController alloc] initWithNibName:#"celluleConnecte" bundle:nil];
cell = (celluleConnecte *)vue.view;
[vue release];
}
else {
asyncImageView* oldImage = (asyncImageView*)
[cell.contentView viewWithTag:999];
[oldImage removeFromSuperview];
}
// Configure the cell.
NSDictionary *dico = [self.pseudoOnline objectAtIndex:indexPath.row];
cell.pseudo.text = [dico objectForKey:#"name"];
cell.sexe.text = [dico objectForKey:#"sexe"];
CGRect frame;
frame.size.width=70; frame.size.height=70;
frame.origin.x=5; frame.origin.y=10;
asyncImageView *asyncImage = [[[asyncImageView alloc] initWithFrame:frame] autorelease];
asyncImage.tag =999;
[asyncImage loadImageFromURL:[NSURL URLWithString:[dico objectForKey:#"photo"]]];
[cell.contentView addSubview:asyncImage];
return cell;
}
it's because you downloading image right in cell, that is wrong. Create a new class of UIImageView and downloading photos there using NSData. There are many examples over the Internet. Here is first i found markj.net/wp/wp-content/uploads/2009/02/asyncimageview.m
I am trying create an accordion type of uitableviewcell that, when the user selects the cell, it expands to display a detailed info view inline similar to how the digg app works. I initially tried replacing the current tablecell with a customcell in cellForRowAtIndex, however the animation looks a bit choppy as you can see the cell being replaced and overall the effect doesn't work too well.
If you look at the digg app and others who have done this it seems that they aren't replacing the current cell but instead perhaps adding a subview to the cell? The original cell however doesn't seem to animate at all and only the new view accordions into the table.
Does anyone have any ideas how to accomplish a similar effect?
I have made some progress using neha's method below and while the cell is animating the correct way it is wreaking havoc with the other cells in the table. What I have done is subclassed UITableViewCell with a custom class which contains an instance of a UIView which actually draws the view which I then add to the table cell's contentview.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
if (selected) {
[self expandCell];
}
}
-(void)expandCell {
self.contentView.frame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 110);
}
Here are all the table delegate methods I am using:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = #"SearchCell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)];
theText.text = #"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:#"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
selectedIndex = indexPath.row;
isSearching = YES;
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
return 110;
}
return rowHeight;
}
It seems now that the cell is expanding but not actually being refreshed so the labels, and textfield aren't being shown. They do however show up when I scroll the cell off and on the screen.
Any ideas?
The Apple way to do is quite simple.
First, you'll need to save the selected indexPath row:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedRowIndex = [indexPath retain];
[tableView beginUpdates];
[tableView endUpdates];
}
I'll explain the begin/end updated part later.
Then, when you have the currently selected index, you can tell the tableView that it should give that row more space.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//check if the index actually exists
if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {
return 100;
}
return 44;
}
This will return height 100 for the selected cell.
Now we can go back to the begin/end updates. That block triggers the reload of all tableView geometry. Moreover, that block is animated, which eventually gives the impressions of the row expanding.
Pawel's beginUpdates/endUpdates trick is good, and I often use it. But in this case you simply need to reload the rows that are changing state, ensuring that you correctly reload them with the desired cell type, and that you return the correct new cell height.
Here is a complete working implementation of what I think you're trying to accomplish:
.h:
#import <UIKit/UIKit.h>
#interface ExpandingTableViewController : UITableViewController
{
}
#property (retain) NSIndexPath* selectedIndexPath;
#end
.m:
#implementation ExpandingTableViewController
#synthesize selectedIndexPath;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier1 = #"Cell1";
static NSString *CellIdentifier2 = #"Cell2";
UITableViewCell *cell;
NSIndexPath* indexPathSelected = self.selectedIndexPath;
if ( nil == indexPathSelected || [indexPathSelected compare: indexPath] != NSOrderedSame )
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %d", indexPath.row];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier2] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %d", indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat: #"(expanded!)", indexPath.row];
}
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( self.selectedIndexPath != nil && [self.selectedIndexPath compare: indexPath] == NSOrderedSame )
{
return tableView.rowHeight * 2;
}
return tableView.rowHeight;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray* toReload = [NSArray arrayWithObjects: indexPath, self.selectedIndexPath, nil];
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths: toReload withRowAnimation: UITableViewRowAnimationMiddle];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
#end
If you don't want to reload the cell (you want to keep your existing cell and just change the size, and likely add/remove some subviews), then simply do the beginUpdates/endUpdates trick in didSelectRowAtIndexPath:, and call some method on your cell to incite the layout change. beginUpdates/endUpdates will prompt the tableView to re-query the heights for each cell - so be sure to return the correct value.
Create a class that subclasses UITableviewcell in your project. Create this class' nib and set its parent to be the class in your project with tableview and override its -
(void)setSelected:(BOOL)selected animated:(BOOL)animated
Write methods contractCell() and expandCell() in this class, and provide the height of the cells you want in expandCell method. Call this methods appropriately based on some flags set to identify wheather the cell is in expanded state or contracted state. Use your tableview's
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
method to handle selection of cells.
Replace your cellForRowAtIndexPath function with this one.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = #"SearchCell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0,
10.0, cell.contentView.bounds.size.width
-20, 22.0)];
theText.text = #"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 +
46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0,
88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:#"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
}
create array wof dictionary which have a key Select_sts which is 0 in start when click its change 1
accourding u change table
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 40.0)];
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.opaque = NO;
headerLabel.textColor = [UIColor blackColor];
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.frame = CGRectMake(5.0, 10.0, 300.0, 20.0);
headerLabel.text=[NSString stringWithFormat: #"PNR %#",[[record objectAtIndex:section] objectForKey:#"number"]];
customView.backgroundColor=[UIColor whiteColor];
btn_openClose.tag=section+10000;
btn_openClose.backgroundColor=[UIColor clearColor];
// [btn_openClose setImage:[UIImage imageNamed:#"down_arrow.png"] forState:UIControlStateNormal];
[btn_openClose addTarget:self action:#selector(collapseExpandButtonTap:) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:btn_openClose];
}
- (void) collapseExpandButtonTap:(id) sender{
int indexNo=[sender tag]-10000;
// NSLog(#"total_record %#",[total_record objectAtIndex:indexNo]);
NSMutableDictionary *mutDictionary = [[total_record objectAtIndex:indexNo] mutableCopy];
if([[mutDictionary objectForKey:#"Select_sts"] integerValue]==0)
[mutDictionary setObject:[NSNumber numberWithInt:1] forKey:#"√"];
else
[mutDictionary setObject:[NSNumber numberWithInt:0] forKey:#"Select_sts"];
[total_record replaceObjectAtIndex:indexNo withObject:mutDictionary];
// [table_view beginUpdates];
// [table_view reloadData];
// [table_view endUpdates];
NSMutableIndexSet *indetsetToUpdate = [[NSMutableIndexSet alloc]init];
[indetsetToUpdate addIndex:indexNo]; // [indetsetToUpdate addIndex:<#(NSUInteger)#>]
// You can add multiple indexes(sections) here.
[table_view reloadSections:indetsetToUpdate withRowAnimation:UITableViewRowAnimationFade];
}
I have a UITableView in an iPhone application which I am refreshing (by calling [self.tableView reloadData] in the action method for a UISegmentedControl dynamically embedded in one of the UITableView cells. The table view is refreshed to update a text value for one of the cells.
However, the following code seems to produce an unwanted side-effect. It appears that each time the UITableView refreshes it creates a new instance of the UISegmentedControl (and possibly the images - I'm not sure) over the existing one(s).
The only reason I notice this is that with each refresh a barely perceptible border starts to form around the UISegmentedControl and the application slows noticeably. I would be extremely grateful for any suggestions/code-solutions to my current predicament.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSUInteger section = indexPath.section;
NSUInteger row = indexPath.row;
// Set up the cell...
//populates the personal info section
if (section == kPersonalInfoAddSection) {
if (row == kNameRow) {
//Other code irrelevant to this question was removed for the sake of clarity
}
else if(row == kHeightRow) {
cell.imageView.image = [UIImage imageNamed:#"tableview_height_label.png"];
//THIS IS THE TEXT I'M TRYING TO UPDATE
cell.textLabel.text = [Formatter formatHeightValue:mainUser.heightInMM forZone:self.heightZone];
cell.detailTextLabel.text = REQUIRED_STRING;
}
}
//populates the units section
if (section == kUnitsSection) {
if (row == kHeightUnitsRow) {
NSArray *heightUnitsSegments = [[NSArray alloc] initWithObjects:FT_AND_IN_STRING, M_AND_CM_STRING, nil];
UISegmentedControl *heightUnitControl = [[UISegmentedControl alloc] initWithItems:heightUnitsSegments];
CGRect segmentRect = CGRectMake(90, 7, 200, 30);
[heightUnitControl setFrame:segmentRect];
//[heightUnitControl setSelectedSegmentIndex:0];
[heightUnitControl addTarget:self action:#selector(heightSegmentClicked:) forControlEvents:UIControlEventValueChanged];
heightUnitControl.tag = kHeightSegmentedControlTag;
cell.textLabel.text = #"Height:";
cell.detailTextLabel.text = #"(units)";
[cell.contentView addSubview:heightUnitControl];
[heightUnitsSegments release];
[heightUnitControl release];
}
else if(row == kWeightUnitsRow) {
//Other code irrelevant to this question was removed for the sake of clarity
}
}
return cell;
}
Thank you all in advance!
You're right, it is creating a new instance of the UISegmentedControl. It's because you are using a generic cell identifier, #"Cell", then adding the UISegmentedControl each time, never removing it. The cells get cached containing the UISegmentedControl, you retrieve the cached cell and add the control again.
You could use a more specific cell identifier and if cell != nil you know it contains the UISegmentedControl already. Or create a new cell each time that way you're not using a cached cell that already contains the control.
With the image view you just set the cells image view property without adding a new view to the cell so that one is ok, it gets replaced each time.
Since the text you are trying to update doesn't have to do with the UISegmentedControl I think you should be able to use a more specific cell identifier and add the control only on cell creation.
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr1=[NSArray arrayWithObjects:#"img1.jpg",#"img2.jpg",nil];
NSArray *arr2=[NSArray arrayWithObjects:#"img1.jpg",#"img2.jpg",#"img3.jpg",#"img4.jpg",#"img5.jpg",#"img6.jpg",nil];
NSArray *arr3=[NSArray arrayWithObjects:#"img6.jpg",#"img5.jpg",#"img2.jpg",#"img1.jpg",nil];
Imgs = [[NSArray alloc] initWithArray:[NSArray arrayWithObjects:arr1,arr2,arr3,nil]];
NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:#"Ahmedabad",#"Name",#"Picture 5.png",#"Rating",#"Picture 1.png",#"Photo",arr1,#"img",nil];
NSDictionary *dic2=[NSDictionary dictionaryWithObjectsAndKeys:#"Rajkot",#"Name",#"Picture 5.png",#"Rating",#"Picture 2.png",#"Photo",nil];
NSDictionary *dic3=[NSDictionary dictionaryWithObjectsAndKeys:#"Baroda",#"Name",#"Picture 5.png",#"Rating",#"Picture 7.png",#"Photo",nil];
tblArray=[[NSArray alloc] initWithObjects:dic1,dic2,dic3,nil];
[myTbl reloadData];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden=NO;
[self.navigationController.navigationBar setUserInteractionEnabled:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.navigationBarHidden=YES;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [tblArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifer=[NSString stringWithFormat:#"%i",indexPath.row];
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifer];
if(cell==nil){
cell=[self myCustomCell:CellIdentifer dicToSet:[tblArray objectAtIndex:indexPath.row]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
return cell;
}
-(UITableViewCell*)myCustomCell:(NSString*)CellIdentifer dicToSet:(NSDictionary*)dicToSet{
UITableViewCell *cell=[[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 44) reuseIdentifier:CellIdentifer] autorelease];
UIImageView *imgV=[[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 40, 40)];
[imgV setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Photo"]]];
[cell addSubview:imgV];
[imgV release];
UILabel *lbl=[[UILabel alloc] initWithFrame:CGRectMake(44, 2, 276, 20)];
[lbl setText:[dicToSet valueForKey:#"Name"]];
[cell addSubview:lbl];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setFont:[UIFont fontWithName:#"Helvetica-Bold" size:18]];
[lbl release];
UIImageView *imgV1=[[UIImageView alloc] initWithFrame:CGRectMake(44, 24, 70, 20)];
[imgV1 setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Rating"]]];
[cell addSubview:imgV1];
[imgV1 release];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
nxtPlcDtl=[[plcFullDtl alloc] initWithNibName:#"plcFullDtl" bundle:nil];
nxtPlcDtl.dict=[[NSDictionary alloc] initWithDictionary:[tblArray objectAtIndex:indexPath.row]];
nxtPlcDtl.Imgs = [Imgs objectAtIndex:indexPath.row];
nxtPlcDtl.comment1 = [comment1 objectAtIndex:indexPath.row];
nxtPlcDtl.vedio = [vedio objectAtIndex:indexPath.row];
[self.navigationController pushViewController:nxtPlcDtl animated:YES];
}