Asynchronous data in UITableView - iphone

// 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

Related

show images of same width and height in cell of a table

I am using a table view(list view) there i am displaying images in cells,Images are displaying but not of same size its all of different size.I want all the images of same height and width.
Can any one give me the code for that.
Tnx..
Do like this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell=nil;
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
CGRect imageFrame = CGRectMake(2, 8, 40, 40);
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
UIImageView *customImage = [[[UIImageView alloc] initWithFrame:imageFrame] autorelease];
customImage.image=img;
[cell.contentView addSubview:customImage];
}
return cell;
}
just add image with frame in cellForRowAtIndexPath: method like bellow..
you can also use UIImageView instead of AsynchImageView
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ImageCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]
autorelease];
} else {
AsyncImageView* oldImage = (AsyncImageView*)
[cell.contentView viewWithTag:999];
[oldImage removeFromSuperview];
}
CGRect frame;
frame.size.width=75; frame.size.height=75;
frame.origin.x=0; frame.origin.y=0;
AsyncImageView* asyncImage = [[[AsyncImageView alloc]
initWithFrame:frame] autorelease];
asyncImage.tag = 999;
NSURL* url = [imageDownload
thumbnailURLAtIndex:indexPath.row];
[asyncImage loadImageFromURL:url];
[cell.contentView addSubview:asyncImage];
return cell;
}
also See This Demo for your requirement
i hope this help you...
In tableview datasource method -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath provide frame for image view
cell.imageView.frame

NSMutableArray data not loading in tableView in iPhone?

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.

uitableview duplicate images

I have table view that showing hotels and if they favorite or not. If hostel are favorite, in hostels's row accessory view I placed image of favorite. But the image not showed only at target's hostel. I placed randomly in other cells in the tableView. Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 50) reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
//First get the dictionary object
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Countries"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
if (![favorites count] == 0) {
if ([favorites containsObject:[array objectAtIndex:indexPath.row]]) {
NSUInteger indexx = [favorites indexOfObject:cellValue];
if ([[favorites objectAtIndex:indexx] isEqual:cellValue]) {
// here is the image view
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImage:[UIImage imageNamed:#"small_ItsMyFavorite.png"]];
imageView.frame = CGRectMake(276, 0, 50, 50);
[cell addSubview:imageView];
[imageView release];
}
}
}
}
}
return cell;
}
I am searching and searching, what is the problem?
Since UITableView is reusing cells your design has some problems.
Your adding an UIImageView to the cell, even when it is reused, so when for instance you have 50 rows and you scroll all the way down, each time a cell is reused, you are adding an UIImageView to the cell. And so flushing the memory.
Better would be to subclass UITableViewCell in which you add the UIImageView. Do not forget to override the prepareForReuse method where you would set the image of your UIImageView to nil
Since UITableViewCell objects are recycled, you need to add an else branch to clear off the image when the hostel is not favorite. As you currently have it, a cell that has been used to display a favorite once would contain an image forever.
if ([[favorites objectAtIndex:indexx] isEqual:cellValue]) {
// here is the image view
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImage:[UIImage imageNamed:#"small_ItsMyFavorite.png"]];
imageView.frame = CGRectMake(276, 0, 50, 50);
[cell addSubview:imageView];
[imageView release];
} else {
// Find the UIImageView in the subviews of your cell,
// and remove it from superview.
}
you must do something like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 50) reuseIdentifier:CellIdentifier] autorelease];
}
else
{
[[cell.contentView viewWithTag:999] removeFromSuperView];
}
// Set up the cell...
//First get the dictionary object
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Countries"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
if (![favorites count] == 0) {
if ([favorites containsObject:[array objectAtIndex:indexPath.row]]) {
NSUInteger indexx = [favorites indexOfObject:cellValue];
if ([[favorites objectAtIndex:indexx] isEqual:cellValue]) {
// here is the image view
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImage:[UIImage imageNamed:#"small_ItsMyFavorite.png"]];
imageView.frame = CGRectMake(276, 0, 50, 50);
imageView.tag = 999; // for example
[cell addSubview:imageView];
[imageView release];
}
}
}
}
}
return cell;
}

Returning more cells in a UITableView

I am using MGTwitterEngine and have almost EVERYTHING figured out, but for some reason I cannot figure out how to return more tweets in my timeline! It receives around 20 tweets by the method I am using and if I add a integer for example: return count = 100;, I can tell I now have 100 cells when it loads and by the scroll indicator but when I scroll to that 18- 19 cell I get this error:
SIGABRT
-[NSMutableArray objectAtIndex:]: index 20 beyond bounds [0 .. 19]'
* Call stack at first throw:
I know what it means: theres no more information to receive at cell 20. I'm baffled and went in and out of MGTwitterEngine looking for a default tweet count but I can't find it. I am using the dump to create my NSStrings and the dump only seems to give around 20 tweets per login. Please help, any suggestions are good in my book! Thank you!
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int count = [tweets count];
// Return just enough cells to fill the screen during loading ....
if (count == 0)
count = MyCustomRowCount;
else {
//Here is where I think I need to add a else return integer but dont know how
}
return count;
return [tweets count];
return [authors count];
return [avatarsURL count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
[cell autorelease];
}
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"]autorelease];
/*
//Here it adds a nice shadow to the table view but will crash on rotation and send a
wird dump !!!????
tableView.layer.shadowColor = [[UIColor blackColor] CGColor];
tableView.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
tableView.layer.shadowRadius = 8.0f;
tableView.layer.shadowOpacity = 1.0f;
*/
[cell.textLabel setNumberOfLines:1];
[cell.textLabel setText:[(Tweet*)[authors objectAtIndex:indexPath.row] author]];
[cell.detailTextLabel setText:[(Tweet*)[tweets objectAtIndex:indexPath.row] tweet]];
[cell.detailTextLabel setNumberOfLines:10];
[cell.textLabel setTextColor:[UIColor darkGrayColor]];
[cell.textLabel setShadowColor:[UIColor whiteColor]];
[cell.textLabel setShadowOffset:CGSizeMake(0.5, 0.5)];
[cell.detailTextLabel setTextColor:[UIColor blackColor]];
//[cell.detailTextLabel setText:[(Tweet*)[retweetCount objectAtIndex:indexPath.row]
reTweetCount]];
[cell.textLabel setUserInteractionEnabled:YES];
[cell.contentView setMultipleTouchEnabled:YES];
// cell.text = [[NSString alloc] initWithFormat:#"Cell :%i", indexPath.row];
// Here we use the new provided setImageWithURL: method to load the web image with
SDWebImageManager
[cell.imageView setImageWithURL:[NSURL URLWithString:[(Tweet*)[avatarsURL
objectAtIndex:indexPath.row]avatarURL]]
placeholderImage:[UIImage imageNamed:#"avatar.png"]];
//add gradient to cell
UIImage *gradient = [UIImage imageNamed:#"gradientcell2.png"];
UIImageView *cellimage = [[UIImageView alloc] initWithImage:gradient];
cellimage.contentMode = UIViewContentModeScaleToFill;
cell.backgroundView = cellimage;
[cellimage release];
UIImage *selectedGradient = [UIImage imageNamed:#"selectedcell.png"];
UIImageView *selectedCell = [[UIImageView alloc] initWithImage:selectedGradient];
selectedCell.contentMode = UIViewContentModeScaleToFill;
cell.selectedBackgroundView = selectedCell;
[tableView setBackgroundColor:[UIColor clearColor]];
return cell;
}
//get cell accessory
-(UITableViewCellAccessoryType)tableView:(UITableView *)tableView
accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row < [tweets count]){
}
return UITableViewCellAccessoryDisclosureIndicator;
}
// custom hieght
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
return 80;
}
//select tweet bring to detail view ..... Also bring in the Users information who made the tweet!
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
//Get the selected tweets
NSString *selectedTweet = [(Tweet*)[tweets objectAtIndex:indexPath.row] tweet];
NSString *selectedUser = [(Tweet*)[tweets objectAtIndex:indexPath.row] author];
NSString *selectedUserInfo = [(Tweet*)[tweets objectAtIndex:indexPath.row] user];
NSString *retweetCount = [(Tweet*)[tweets objectAtIndex:indexPath.row] reTweetCount ];
// NSString *selectedUserFriendsCount = [(Tweet*)[tweets objectAtIndex:indexPath.row] userFriendsCount];------HUH? NO soup for ME!
NSString *selectedUserFollowersCount = [(Tweet*)[tweets objectAtIndex:indexPath.row] userFollowersCount];
//Initialize the detail view controller and display it.
TwitterDetailViewController*dvController = [[TwitterDetailViewController alloc]
initWithNibName:#"TwitterDetailViewController" bundle:[NSBundle mainBundle]];
dvController.selectedTweet = selectedTweet;
dvController.selectedUser = selectedUser;
dvController.selectedUserInfo = selectedUserInfo;
// dvController.selectedUserFriendsCount = selectedUserFriendsCount;------Doesnt reconize the call for some odd reason!
dvController.selectedUserFollowersCount = selectedUserFollowersCount;
dvController.retweetCount = retweetCount;
dvController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:dvController animated:YES];
//[self.navigationController pushViewController:webController animated:YES];-------would rather use navagation controller for several obvious reasons
[dvController release];
dvController = nil;
}
UITableView doesn't it like it when you gave it something inconsistant. If you change the model, you need to call [tableView reloadData] or if you want to animate the changes call [tableView beingUpdate][tableView endUpdate] with all the insert/remove cell operations in the middle.
On another note, I'm not sure why you doing here:
NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
[cell autorelease];
}
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"cell"];
[cell autorelease];
First if (cell == nil), calling auto release on it won't do anything.
The reuse identifier thing is a flyweight pattern. If dequeueReusableCellWithIdentifier: returns nil, it means it doesn't have a cell object in the pool for you to use and you should alloc a new one for it. dequeueReusableCellWithIdentifier also already returns an autorelease object.
Instead try this:
NSString *identifier = #"mytweetcell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
}

Accordion table cell - How to dynamically expand/contract uitableviewcell?

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];
}