Loading data issue in UITableview - objective-c

I created an application using UITableView. I parsing the data from URL and listed in UITableView.
But in UITableView, the first the data only displayed again and again.
I don't know why this problem occurred.
My code is as below:
-(UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
CGRect frame = CGRectMake(10.0f, 5.0, 300.0, 55);
valueField = [[UILabel alloc] initWithFrame:frame];
[valueField setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
valueField.tag = 111;
valueField.font=[UIFont fontWithName:#"Helvetica" size:16.0];
valueField.textAlignment = UITextAlignmentLeft;
valueField.lineBreakMode=UILineBreakModeWordWrap;
valueField.numberOfLines = 0;
valueField.textColor = [UIColor whiteColor];
valueField.highlightedTextColor = [UIColor whiteColor];
valueField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
valueField.adjustsFontSizeToFitWidth = YES;
valueField.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
valueField.text=[title1 objectAtIndex:count1];
[cell.contentView addSubview:valueField];
UIImage *favOn = [UIImage imageNamed:#""];
UIImage *favOff = [UIImage imageNamed:#""];
titlebutton = [[UIButton alloc] initWithFrame:CGRectMake(10.0f, 15.0, 300.0, 55)];
[titlebutton setTag:indexPath.row];
//titlebutton.tag = 111;
[titlebutton setImage:favOff forState:UIControlStateNormal];
[titlebutton setImage:favOn forState:UIControlStateSelected];
if([self getFavState:#"111"])
{
[titlebutton setSelected:YES];
}
else
{
[titlebutton setSelected:NO];
}
[titlebutton addTarget:self action:#selector(favButtonSwitch:) forControlEvents:UIControlEventTouchUpInside];
[titlebutton setBackgroundColor:[UIColor clearColor]];
[titlebutton setTitle:#"" forState:UIControlStateNormal];
[cell.contentView addSubview:titlebutton];
CGSize labelSize = [valueField.text sizeWithFont:valueField.font constrainedToSize:valueField.frame.size lineBreakMode:UILineBreakModeWordWrap];
int labelHeight = labelSize.height;
NSLog(#"labelHeight = %d", labelHeight);
frame = CGRectMake(10.0f, 40.0, 300.0, 55);
pubField = [[UILabel alloc] initWithFrame:frame];
[pubField setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
pubField.tag = 111;
pubField.font=[UIFont fontWithName:#"Helvetica" size:12.0];
pubField.textAlignment = UITextAlignmentLeft;
pubField.lineBreakMode=UILineBreakModeWordWrap;
pubField.numberOfLines = 0;
pubField.textColor = [UIColor whiteColor];
pubField.highlightedTextColor = [UIColor whiteColor];
pubField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
pubField.adjustsFontSizeToFitWidth = YES;
pubField.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
pubField.text=[pubDate objectAtIndex:indexPath.row];
[cell.contentView addSubview:pubField];
frame = CGRectMake(5.0, 70.0, 300.0, 55);
desField = [[UILabel alloc] initWithFrame:frame];
[desField setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
desField.tag = 111;
desField.font=[UIFont fontWithName:#"Helvetica" size:13.0];
desField.textAlignment = UITextAlignmentLeft;
desField.lineBreakMode=UILineBreakModeWordWrap;
desField.numberOfLines = 0;
desField.textColor = [UIColor whiteColor];
desField.highlightedTextColor = [UIColor whiteColor];
desField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
desField.adjustsFontSizeToFitWidth = YES;
desField.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
desField.text=[description objectAtIndex:indexPath.row];
[cell.contentView addSubview:desField];
}
UIImage *patternImage = [UIImage imageNamed:#"bg.jpg"];
UIView *backView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
backView.backgroundColor = [UIColor colorWithPatternImage: patternImage];
cell.backgroundView = backView;
NSString *image1 =[images objectAtIndex:indexPath.row];
NSLog(#"Images ..... = %#",image1);
NSData *mydata = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[images objectAtIndex:indexPath.row]]];
UIImage *myimage = [[UIImage alloc] initWithData:mydata];
UIImageView *imageView = [ [ UIImageView alloc ] initWithImage: myimage ];
imageView.frame = CGRectMake(10.0f, 110.0f, 120.0f, 120.0f);
[cell.contentView addSubview:imageView];
return cell;
}

do all the alloc/init and all things, that will be the same in any cell in the
if(cell==nil){
//<-- here
}
while setting text and any thing that changes by the specific data outside the block
if(cell==nil){
}
//<-- here
i.e:
if(cell==nil){
//....
valueField.tag = 111;
valueField.font = [UIFont fontWithName:# "Helvetica" size:16.0];
valueField.textAlignment = UITextAlignmentLeft;
valueField.lineBreakMode = UILineBreakModeWordWrap;
valueField.numberOfLines = 0;
valueField.textColor = [UIColor whiteColor];
valueField.highlightedTextColor = [UIColor whiteColor];
valueField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
valueField.adjustsFontSizeToFitWidth = YES;
valueField.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
[cell.contentView addSubview : valueField];
//....
}
//....
valueField.text = [title1 objectAtIndex:count1];
//....

the first cell data is getting displayed in all the cells because when you initialize and create your reusable cell, you fill the data there, you need to initialize a reusable cell that doesnt have all its values set, and then set this information for each cell. That is, you need to have all the information you want for each particular cell outside the if(cell==nil) part of this code, and rely on the indexPath to know which cell you are in, and feed in different data based on this.

You seem to be constructing the subviews of the cell correctly when there is no reusable cell available. The question is, what does your code do when you do dequeue a reusable cell? It appears that you do nothing. You should move any row-specific initialization (setting label text values, images, etc.) outside the check for whether the dequeued cell is nil. In this way, whether you just constructed a new cell or dequeued a previously-created cell, the data being displayed correctly correlates to the row being displayed.

Well actually your code this way is quite hard to decode,
but first of all, you declare a lot of tag that should be used to retrieve the UIViews you're declaring.
Unfortunately these are all the same (tags) so you might never get what you want. You should maybe put in some constant in your header file like:
#define kPubLabel 100
then use them.
then you usually retrieve these after declaring your cell to populate them.
In the mean time, retrieving your images from url in this method is one of the best way to have your application being slow, since each time you scroll, you'll have to re-fetch your image from where it come from causing your table view to "freeze".
Finally, the only thing that might change, according to your code is the imageView that you add to your frame. You usually have an ImageView in which you put an image that you might have stored/cached but rarely change the contentView of a cell.
ie
Maybe you should externalize your cell building code in a class overriding UITableViewCell.
Put different tags on every element in your cell to retrieve them in your method.
Retrieve your elements in your method according to there tags.
Populate and only populate them in your method.
Retrieve your image once and for all for performance improval.
I'm not sure this will help, but in my point of view, there are actually a lot work to do in your code.

Related

Cannot change the Y cordinate of the UILabel programmatically

hi Im programmatically creating an UILabel like this
`
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[[UILabel alloc] init] initWithFrame:CGRectMake(0.0, _photoView.frame.size.height, _photoView.frame.size.width, 100.0)];
// _titleLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
_titleLabel.backgroundColor =[UIColor clearColor];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14];
_titleLabel.textAlignment = NSTextAlignmentRight;
[self addSubview:_titleLabel];
}
return _titleLabel;
}`
this _photoView is an UIImageView I have created already. I want to change the UILabel View Y value. But the problem is when I change this second parameter label y position is not changing. Any one can tell e the reason for this.
And this is how I created the ImageView
`
- (UIImageView *)photoView {
if (!_photoView) {
_photoView = [[UIImageView alloc] init];
_photoView.contentMode = UIViewContentModeScaleAspectFill;
_photoView.clipsToBounds = YES;
_photoView.layer.cornerRadius = 5;
_photoView.clipsToBounds = YES;
[self addSubview:_photoView];
}
return _photoView;
}`
Thanks
In this line , you have used two types init
[[[UILabel alloc] init] initWithFrame:CGRectMake(0.0, _photoView.frame.size.height, _photoView.frame.size.width, 100.0)]
change this line to
[[UILabel alloc] initWithFrame:CGRectMake(0.0, _photoView.frame.size.height, _photoView.frame.size.width, 100.0)]

Adding subviews to UITableViewCells causing issue while scrolling

I'm absolutely stumped on how to fix this issue.
So I have a UITableView and in the delegate method cellForRowAtIndex: I'm adding several subviews to each cell if the cell is nil (the initial building of the table view). Everything works well and the table view is built, however, when I scroll down a little in the application, the app all of a sudden crashes with SIGBART and gives me the error
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSIndexPath setImage:]: unrecognized selector sent to class 0x3c361e68'** It's weird because I'm not even calling a setImage method anywhere in my code.
Here is the code for the delegate method.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UIImageView* imageView;
UILabel* ttitle;
UILabel* ttitle2;
UILabel* ttitle3;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure cell:
// *** This section should configure the cell to a state independent of
// whatever row or section the cell is in, since it is only executed
// once when the cell is first created.
imageView=[[UIImageView alloc]initWithFrame:CGRectMake(10.0, 11.0, 50.0, 50.0)];
[imageView setContentMode:UIViewContentModeScaleAspectFill];
imageView.layer.masksToBounds=YES;
imageView.layer.cornerRadius=5.0;
[cell.contentView addSubview:imageView];
ttitle = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 7.0, 200, 20)] autorelease];
ttitle.textColor= [UIColor blackColor];
ttitle.numberOfLines=1;
ttitle.backgroundColor=[UIColor clearColor];
ttitle.font=[UIFont fontWithName:#"Arial Bold" size:15.0];
[cell.contentView addSubview:ttitle];
if (indexPath.row==0) {
CGSize size=[[[data objectAtIndex:indexPath.row] valueForKey:#"content"] sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(265.0f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
ttitle2 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 27.5, 200, size.height)] autorelease];
ttitle2.textColor= [UIColor darkGrayColor];
ttitle2.backgroundColor=[UIColor clearColor];
ttitle2.numberOfLines=0;
ttitle2.textAlignment = NSTextAlignmentLeft;
ttitle2.lineBreakMode=NSLineBreakByWordWrapping;
ttitle2.font=[UIFont fontWithName:#"Arial" size:14.0];
[cell.contentView addSubview:ttitle2];
ttitle3 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, ttitle2.frame.origin.y+ttitle2.frame.size.height-8.0, 210, 40)] autorelease];
ttitle3.textColor= [UIColor darkGrayColor];
ttitle3.backgroundColor=[UIColor clearColor];
ttitle3.numberOfLines=1;
ttitle3.textAlignment = NSTextAlignmentLeft;
ttitle3.lineBreakMode=NSLineBreakByWordWrapping;
ttitle3.font=[UIFont fontWithName:#"Arial" size:11.0];
[cell.contentView addSubview:ttitle3];
}
else{
CGSize size=[[[data objectAtIndex:indexPath.row] valueForKey:#"content"] sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(265.0f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
ttitle2 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 27.0, 200, size.height)] autorelease];
ttitle2.textColor= [UIColor darkGrayColor];
ttitle2.backgroundColor=[UIColor clearColor];
ttitle2.numberOfLines=0;
ttitle2.textAlignment = NSTextAlignmentLeft;
ttitle2.lineBreakMode=NSLineBreakByWordWrapping;
ttitle2.font=[UIFont fontWithName:#"Arial" size:14.0];
[cell.contentView addSubview:ttitle2];
ttitle3 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, ttitle2.frame.origin.y+ttitle2.frame.size.height-9.0, 210, 40)] autorelease];
ttitle3.textColor= [UIColor darkGrayColor];
ttitle3.backgroundColor=[UIColor clearColor];
ttitle3.numberOfLines=1;
ttitle3.textAlignment = NSTextAlignmentLeft;
ttitle3.lineBreakMode=NSLineBreakByWordWrapping;
ttitle3.font=[UIFont fontWithName:#"Arial" size:11.0];
[cell.contentView addSubview:ttitle3];
}
}
// Customize cell:
// *** This section should customize the cell depending on what row or section
// is passed in indexPath, since this is executed every time this delegate method
// is called.
imageView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[data objectAtIndex:indexPath.row] valueForKey:#"thumbnail"]]]];
[ttitle setText:[[data objectAtIndex:indexPath.row] valueForKey:#"name"]];
[ttitle2 setText:[[data objectAtIndex:indexPath.row] valueForKey:#"content"]];
NSString* first=[[[data objectAtIndex:indexPath.row] valueForKey:#"hashtag"] stringByAppendingString:#" "];
NSString* second =[first stringByAppendingString:[[data objectAtIndex:indexPath.row] valueForKey:#"place"]];
NSString* third=[second stringByAppendingString:#" "];
NSString* fourth=[third stringByAppendingString:#"¤ "];
NSString* conversion=[[[data objectAtIndex:indexPath.row] valueForKey:#"counter"] stringValue];
NSString* fifth=[fourth stringByAppendingString:conversion];
[ttitle3 setText:fifth];
return cell;
}
Appreciate the help guys!
*UPDATED CODE
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UIImageView* imageView;
UILabel* ttitle;
UILabel* ttitle2;
UILabel* ttitle3;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure cell:
// *** This section should configure the cell to a state independent of
// whatever row or section the cell is in, since it is only executed
// once when the cell is first created.
imageView=[[UIImageView alloc]initWithFrame:CGRectMake(10.0, 11.0, 50.0, 50.0)];
[imageView setContentMode:UIViewContentModeScaleAspectFill];
imageView.layer.masksToBounds=YES;
imageView.layer.cornerRadius=5.0;
imageView.tag=1;
[cell.contentView addSubview:imageView];
ttitle = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 7.0, 200, 20)] autorelease];
ttitle.textColor= [UIColor blackColor];
ttitle.numberOfLines=1;
ttitle.tag=69;
ttitle.backgroundColor=[UIColor clearColor];
ttitle.font=[UIFont fontWithName:#"Arial Bold" size:15.0];
[cell.contentView addSubview:ttitle];
if (indexPath.row==0) {
CGSize size=[[[data objectAtIndex:indexPath.row] valueForKey:#"content"] sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(265.0f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
ttitle2 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 27.5, 200, size.height)] autorelease];
ttitle2.textColor= [UIColor darkGrayColor];
ttitle2.backgroundColor=[UIColor clearColor];
ttitle2.numberOfLines=0;
ttitle2.tag=70;
ttitle2.textAlignment = NSTextAlignmentLeft;
ttitle2.lineBreakMode=NSLineBreakByWordWrapping;
ttitle2.font=[UIFont fontWithName:#"Arial" size:14.0];
[cell.contentView addSubview:ttitle2];
ttitle3 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, ttitle2.frame.origin.y+ttitle2.frame.size.height-8.0, 210, 40)] autorelease];
ttitle3.textColor= [UIColor darkGrayColor];
ttitle3.backgroundColor=[UIColor clearColor];
ttitle3.numberOfLines=1;
ttitle3.tag=71;
ttitle3.textAlignment = NSTextAlignmentLeft;
ttitle3.lineBreakMode=NSLineBreakByWordWrapping;
ttitle3.font=[UIFont fontWithName:#"Arial" size:11.0];
[cell.contentView addSubview:ttitle3];
}
else{
CGSize size=[[[data objectAtIndex:indexPath.row] valueForKey:#"content"] sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(265.0f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
ttitle2 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 27.0, 200, size.height)] autorelease];
ttitle2.textColor= [UIColor darkGrayColor];
ttitle2.backgroundColor=[UIColor clearColor];
ttitle2.numberOfLines=0;
ttitle2.tag=70;
ttitle2.textAlignment = NSTextAlignmentLeft;
ttitle2.lineBreakMode=NSLineBreakByWordWrapping;
ttitle2.font=[UIFont fontWithName:#"Arial" size:14.0];
[cell.contentView addSubview:ttitle2];
ttitle3 = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, ttitle2.frame.origin.y+ttitle2.frame.size.height-9.0, 210, 40)] autorelease];
ttitle3.textColor= [UIColor darkGrayColor];
ttitle3.backgroundColor=[UIColor clearColor];
ttitle3.numberOfLines=1;
ttitle3.tag=71;
ttitle3.textAlignment = NSTextAlignmentLeft;
ttitle3.lineBreakMode=NSLineBreakByWordWrapping;
ttitle3.font=[UIFont fontWithName:#"Arial" size:11.0];
[cell.contentView addSubview:ttitle3];
}
imageView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[data objectAtIndex:indexPath.row] valueForKey:#"thumbnail"]]]];
[ttitle setText:[[data objectAtIndex:indexPath.row] valueForKey:#"name"]];
[ttitle2 setText:[[data objectAtIndex:indexPath.row] valueForKey:#"content"]];
NSString* first=[[[data objectAtIndex:indexPath.row] valueForKey:#"hashtag"] stringByAppendingString:#" "];
NSString* second =[first stringByAppendingString:[[data objectAtIndex:indexPath.row] valueForKey:#"place"]];
NSString* third=[second stringByAppendingString:#" "];
NSString* fourth=[third stringByAppendingString:#"¤ "];
NSString* conversion=[[[data objectAtIndex:indexPath.row] valueForKey:#"counter"] stringValue];
NSString* fifth=[fourth stringByAppendingString:conversion];
[ttitle3 setText:fifth];
}
else {
imageView =[cell viewWithTag:1];
ttitle=[cell viewWithTag:69];
ttitle2=[cell viewWithTag:70];
ttitle3=[cell viewWithTag:71];
}
//STUFFOUTSIDE
// Customize cell:
// *** This section should customize the cell depending on what row or section
// is passed in indexPath, since this is executed every time this delegate method
// is called.
return cell;
}
The problem is that your local variables are not being initialized when the cell is re-used. Here's the current flow for imageView:
UIImageView* imageView;
if (cell == nil)
{
// Create imageView
imageView=...
}
// If cell is being reused (ie cell is not nil) then imageView is nil at this point.
imageView.image=...
When you are reusing a table view cell, tableView:dequeueReusableCellWithIdentifier: returns an actual cell instead of nil and the initialization of imageView is skipped.
You need to "find" the imageView that is in the reused cell in order to make changes to it.
Therefore, I suggest that you modify your logic like this:
UIImageView* imageView;
if (cell == nil)
{
// Create imageView
imageView=...
}
else
{
imageView = // get a reference to the imageView
}
imageView.image=...
So now, of course, the question is "how?".
A very common way is to set the tag of the view when you create it so that you can easily retrieve it at a later time. You would use this technique like this:
// Use a unique tag number for each subview.
#define MY_IMAGEVIEW_TAG 1000
UIImageView* imageView;
if (cell == nil)
{
// Create imageView
imageView=... // Same as before
imageView.tag = MY_IMAGEVIEW_TAG;
}
else
{
// This is a cell that is being re-used and was previously created.
// Retrieve a reference to the existing image view that is already in the cell
imageView = [cell viewWithTag:MY_IMAGEVIEW_TAG];
}
// Now imageView is "safe" to use whether it is a new cell or one that is reused!
imageView.image=...
NOTE: If you are doing a lot of this, creating a UITableViewCell subclass that has properties for each of these subviews would make the use of tags and viewWithTag unnecessary, as well as make your code easier to read.
#Inafziger has already posted the correct answer to this question, I just want to explain a little bit more in detail why you're seeing this "weird" crash.
I wouldn't recommend the excessive usage of tags, though. It might be a better idea to create a subclass of UITableViewCell.
You're not initializing your imageView and ttitle variables:
UIImageView *imageView; // imageView can point to anything now!
UILabel* ttitle;
Usually, you'd initialize local variables to nil or 0 (whatever makes sense) when you declare them to avoid such dangling pointers.
Because you're reusing your table view cells cell won't always be nil and your if-clause won't be executed:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) { // Won't be executed if the cell could be dequeued!
...
imageView = ...;
}
Hence, if cell can be dequeued, your imageView and ttitle variables have still not been assigned to anything when you use them!
You're then setting the attributes of the views:
imageView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[data objectAtIndex:indexPath.row] valueForKey:#"thumbnail"]]]];
[ttitle setText:[[data objectAtIndex:indexPath.row] valueForKey:#"name"]];
[ttitle2 setText:[[data objectAtIndex:indexPath.row] valueForKey:#"content"]]
imageView.image = ...; is the same as calling [imageView setImage:...];. You can read more about that here: http://www.cocoacast.com/cocoacast/?q=node/103
And that's when all comes together: imageView isn't initialized and you're calling -setImage: on it. Boom, crash!
In your case imageView points to the NSIndexPath class. This could be anything, though.
Because of that you're effectively calling -setImage: on the NSIndexPath class (equivalent to: +[NSIndexPath setImage:]) and the app crashes with the +[NSIndexPath setImage:]: unrecognized selector sent to class 0x3c361e68 error message.

reloading data of a table view is not working

im making a tableview with checkboxes. I did implement the checkboxes with UIButtons and i can check and uncheck them without problems. The problem came up when i tried to make a "select/unselect all" button and this is the resultant code:
-(IBAction)select:(id)sender{
if (all==YES) {
all=NO;
}
else {
all=YES;
}
[tblPeticiones reloadData];
}
The problem is that the table doesn't reload the data.
Any idea?
Thanks and regards.
EDIT:
I load de data like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Datos
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSString *fInicio = [dateFormatter stringFromDate:[(MAP_Gastos_CiberTRIPS *)[m objectAtIndex:indexPath.row] DEP_DATE]];
NSString *loc = [(MAP_Gastos_CiberTRIPS *)[m objectAtIndex:indexPath.row] LOCATION];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[formatter setCurrencyCode:#"EUR"];
[formatter setLocale:[NSLocale currentLocale]];
NSString *precio = [formatter stringFromNumber:aux];
//Vista
NSString *MyIdentifier = [NSString stringWithFormat:#"MyIdentifier %i", indexPath.row];
CustomTVC *cell = (CustomTVC *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[CustomTVC alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
//CheckBox
UIButton *checkButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[checkButton setFrame:CGRectMake(10, 10, 23, 23)];
if (todos==NO) {
[checkButton setBackgroundImage:[[UIImage imageNamed:#"checkNO.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
checkButton.tag = 0;
}
else {
[checkButton setBackgroundImage:[[UIImage imageNamed:#"checkSI.png"] str etchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
checkButton.tag = 1;
}
[checkButton addTarget:self action:#selector(checkAction:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:checkButton];
[cell.contentView addSubview:checkButton];
//fecha
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(40, 0, 70.0,tableView.rowHeight)] autorelease];
[cell addColumn:0];
label.tag = 1;
label.font = [UIFont boldSystemFontOfSize:12.0];
label.text = fInicio;
label.textAlignment = UITextAlignmentLeft;
label.textColor = [UIColor blackColor];
//label.backgroundColor = [UIColor whiteColor];
label.autoresizingMask = UIViewAutoresizingNone | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:label];
if (indexPath.row % 2 == 0){
label.backgroundColor = [UIColor colorWithRed:233.0/255.0
green:233.0/255.0
blue:233.0/255.0
alpha:1.0];
} else {
label.backgroundColor = [UIColor clearColor];
}
//localización
label = [[[UILabel alloc] initWithFrame:CGRectMake(115, 0, 75.0,tableView.rowHeight)] autorelease];
[cell addColumn:180];
label.tag = 2;
label.font = [UIFont boldSystemFontOfSize:12.0];
label.text = loc;
label.textAlignment = UITextAlignmentLeft;
label.textColor = [UIColor blackColor];
//label.backgroundColor = [UIColor whiteColor];
label.autoresizingMask = UIViewAutoresizingNone | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:label];
if (indexPath.row % 2 == 0){
label.backgroundColor = [UIColor colorWithRed:233.0/255.0
green:233.0/255.0
blue:233.0/255.0
alpha:1.0];
} else {
label.backgroundColor = [UIColor clearColor];
}
}
return cell;
}
Debug the problem
Check datasource methods of tableView whether they are being called or not after reload?
You should store which rows are checked in an array. Then check this array when you load / reload the tableview (in cellForRowAtIndex) to see if the row should be checked.
Then if you want to select all or none, just delete or add them to the array and reload the tableview.
If you need help implementing this, let me know.
i found the problem. This is the working code:
-(IBAction)select:(id)sender{
if (all==YES) {
all=NO;
[btnSelAll setBackgroundImage:[[UIImage imageNamed:#"checkSI.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
}else {
all=YES;
[btnSelAll setBackgroundImage:[[UIImage imageNamed:#"checkNO.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
}
NSMutableArray *arrIndex = [NSMutableArray new];
for(int i=0;i<[m count];i++) {
[arrIndex addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.tblPeticiones beginUpdates];
[tblPeticiones reloadRowsAtIndexPaths:arrIndex withRowAnimation:UITableViewRowAnimationNone];
[self.tblPeticiones endUpdates];
[tblPeticiones reloadData];
}
Some comments about your code:
There seems to be global variable called all, whose value you toggle, when button is pressed. However inside cellForRowAtIndexPath you check value of another global variable called todos. Is there some connection between these variables?
You change checkbox background image only, when you create a new cell. Since cells are recycled, you need to move this code outside if (cell == nil) i.e. afterwards, where you are customizing a recycled cell
You should only check whether if (todos) and if (!todos), don't compare to values like YES or NO. Also easiest way to toggle a boolean is todos = !todos :)

UITableViewCell - overlapping with previous cells contents

I have this wierd problem with my table
i Have about 20 cells to display
Each cell is about 84px in height
When i click no the cell, i have set a background colour
The first 4 cells are ok, but when i scroll down and click on the 5th cell, the content of each cell starts to overlap with some other content, usually content from 1st 4 cells.
I belive its some cell reusability or drawing issue. Am not sure how to solve it, i have checked through my code, but i am not changing the cell's content on touch.
Here is my code and will add some pics too
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 104;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [stores count];
}
-(UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CGRect Label1Frame = CGRectMake(5, 5, 250, 30);
CGRect Label2Frame = CGRectMake(6, 42, 220, 20);
CGRect Label3Frame = CGRectMake(6, 62, 220, 20);
CGRect Label4Frame = CGRectMake(240,56, 70, 12);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}else{
// a cell is being recycled, remove the old edit field (if it contains one of our tagged edit fields)
UIView *viewToCheck = nil;
viewToCheck = [cell.contentView viewWithTag:1];
if (!viewToCheck) {
[viewToCheck removeFromSuperview];
DebugLog(#"View removed");
}
}
//cell.selectionStyle=UITableViewCellSelectionStyleNone;
[cell setSelectedBackgroundView:bgView];
NSInteger row=indexPath.row;
UILabel *lblTemp;
[[cell contentView] clearsContextBeforeDrawing];
//Line 1
lblTemp=[[UILabel alloc] initWithFrame: Label1Frame];
lblTemp.tag=1;
lblTemp.text=[[stores objectAtIndex:row] objectAtIndex:0] ;
lblTemp.numberOfLines=2;
lblTemp.font = [UIFont boldSystemFontOfSize:13];
lblTemp.adjustsFontSizeToFitWidth=YES;
lblTemp.minimumFontSize=12;
lblTemp.textColor = [UIColor grayColor];
[cell.contentView addSubview:lblTemp];
[lblTemp release];
//Line 2
lblTemp = [[UILabel alloc] initWithFrame:Label2Frame];
lblTemp.tag = 2;
lblTemp.text=[[stores objectAtIndex:row]objectAtIndex:1];
lblTemp.font = [UIFont systemFontOfSize:12];
lblTemp.textColor = [UIColor grayColor ];
lblTemp.textAlignment=UITextAlignmentLeft;
lblTemp.adjustsFontSizeToFitWidth=YES;
lblTemp.minimumFontSize=12;
[cell.contentView addSubview:lblTemp];
[lblTemp release];
//Line 3
lblTemp = [[UILabel alloc] initWithFrame:Label3Frame];
lblTemp.tag = 3;
lblTemp.text=[[stores objectAtIndex:row]objectAtIndex:2];
lblTemp.font = [UIFont systemFontOfSize:12];
lblTemp.textColor = [UIColor grayColor ];
[cell.contentView addSubview:lblTemp];
[lblTemp release];
//Phone button
UIButton *phoneButton=[[UIButton alloc] initWithFrame:CGRectMake(240,16,30,30)];
[phoneButton setBackgroundImage:[UIImage imageNamed:#"phone.png"] forState:UIControlStateNormal];
[phoneButton setTag:row];
[phoneButton addTarget:self action:#selector(dialNumber:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:phoneButton];
//ANnotation button
UIButton *annotation=[[UIButton alloc] initWithFrame:CGRectMake(274,16,30,30)];
[annotation setTag:row];
[annotation setBackgroundImage:[UIImage imageNamed:#"tab.png"] forState:UIControlStateNormal];
[annotation addTarget:self action:#selector(openMap:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:annotation];
[annotation release];
//Distance label
//Line 3
lblTemp = [[UILabel alloc] initWithFrame:Label4Frame];
lblTemp.tag = 4;
lblTemp.text=[[stores objectAtIndex:row]objectAtIndex:5];
lblTemp.textAlignment=UITextAlignmentCenter;
lblTemp.font = [UIFont systemFontOfSize:13];
lblTemp.textColor = [UIColor grayColor ];
[lblTemp setAdjustsFontSizeToFitWidth:YES];
[cell.contentView addSubview:lblTemp];
[phoneButton release];
[lblTemp release];
[cell setNeedsLayout];
[cell setNeedsDisplay];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath ];
for(UILabel *lbl in cell.contentView.subviews){
if([lbl isKindOfClass:[UILabel class]]){
lbl.textColor=[UIColor whiteColor];
}
}
//UITableViewCell *cell1;
//NSString *row=[NSString stringWithFormat:#"%d",indexPath.row];
svm = [[storesMapView alloc] initWithNibName:#"storesMapView" bundle:nil];
[svm initWithXML:stores:indexPath.row];
CGRect theFrame = svm.view.frame;
theFrame.origin = CGPointMake(self.view.frame.size.width, 0);
svm.view.frame = theFrame;
theFrame.origin = CGPointMake(0,0);
theFrame.size=CGSizeMake(320,355);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3f];
svm.view.frame = theFrame;
[UIView commitAnimations];
[subView addSubview:svm.view];
backButton.hidden=NO;
}
I figured it out with some trial and error; if this can help some one
In cellforRowAtIndexPath i tried to clear all the cells subview before drawing the cell
//TRY TO REMOVE ALL CONTENT
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
I would be happy if someone can point me to some easier way
Thanks
You can use
[[[cell contentView] subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
If the cell in not nil, the above code will reduce the time for using the for loop similar to this
for(UIView *eachView in [cell subviews])
[eachView removeFromSuperview];
I also had the same issue.I also had composed tableView with labels.And when I scroll it down the contents got overlapped.But it got solved simply by editing one statement in cellForRowAtIndexPath.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
I think this will solve your problem.
I know this is a bit late, but I had a similar issue where UILabels created for a cell were still part of the cell when it was reused. So each successive update of the tableview created another UILabel on top of the existing one. I moved the creation of the Labels into the if condition as below and it resolved my issue. Hope it helps someone else. Also note no release as I am using ARC.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cityText = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 20)];
cityText.font = [UIFont fontWithName:#"Arial" size:20];
cityText.textAlignment = UITextAlignmentLeft;
cityText.backgroundColor = [UIColor clearColor];
regionText = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 100, 20)];
regionText.font = [UIFont fontWithName:#"Arial" size:20];
regionText.textAlignment = UITextAlignmentLeft;
regionText.backgroundColor = [UIColor clearColor];
}
Setting nil to label text on UITableViewCell subclass 's method prepareForReuse() solved my problem -
override func prepareForReuse() {
super.prepareForReuse()
self.label1.text = nil
self.label2.text = nil
....
}
Shared if it helps anyone!

UITableviewcell loading data issue

I parsed the XML data from a feed. I stored all data in NSArray. I loaded the images and title in UITableview using UILable. But when I use the scroll, the text will be collapsed as follows.
My code is as follows...
-(UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
CGRect frame = CGRectMake(70.0, 00.0, 250.0, 55);
valueField = [[UILabel alloc] initWithFrame:frame];
[valueField setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
valueField.tag = 111;
valueField.font=[UIFont fontWithName:#"Helvetica" size:13.0];
valueField.textAlignment = UITextAlignmentLeft;
valueField.lineBreakMode=UILineBreakModeWordWrap;
valueField.numberOfLines = 0;
valueField.textColor = [UIColor whiteColor];
valueField.text=[title1 objectAtIndex:indexPath.row];
valueField.highlightedTextColor = [UIColor whiteColor];
valueField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
valueField.adjustsFontSizeToFitWidth = YES;
valueField.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
[cell.contentView addSubview:valueField];
[valueField release];
UIImage *patternImage = [UIImage imageNamed:#"bg.jpg"];
UIView *backView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
backView.backgroundColor = [UIColor colorWithPatternImage: patternImage];
cell.backgroundView = backView;
NSString *image1 =[images objectAtIndex:indexPath.row];
NSLog(#"Images ..... = %#",image1);
NSData *mydata = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[images objectAtIndex:indexPath.row]]];
UIImage *myimage = [[UIImage alloc] initWithData:mydata];
UIImageView *imageView = [ [ UIImageView alloc ] initWithImage: myimage ];
imageView.frame = CGRectMake(0.0f, 00.0f, 60.0f, 63.0f);
[cell.contentView addSubview:imageView];
//cell.imageView.image = myimage;
return cell;
}
I don't know how to solve this issue.
Every time the cell is reloaded, the UILabel is added.
Do something like
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
CGRect frame = CGRectMake(70.0, 00.0, 250.0, 55);
valueField = [[UILabel alloc] initWithFrame:frame];
[valueField setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
valueField.tag = 111;
valueField.font=[UIFont fontWithName:#"Helvetica" size:13.0];
valueField.textAlignment = UITextAlignmentLeft;
valueField.lineBreakMode=UILineBreakModeWordWrap;
valueField.numberOfLines = 0;
valueField.textColor = [UIColor whiteColor];
valueField.highlightedTextColor = [UIColor whiteColor];
valueField.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
valueField.adjustsFontSizeToFitWidth = YES;
valueField.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
[cell.contentView addSubview:valueField];
[valueField release];
}
valueField.text=[title1 objectAtIndex:indexPath.row];
To be more specific, since you are dequeuing cells, when you call cellForRowAtIndexPath it potentially can return you a cell that was already created.
That cell already has a label created.
So all of the magic of creating and setting up the custom views in you cell should only be done when dequeueReusableCellWithIdentifier returns a nil value