UIImage displayed in cells with specified string value - iphone

This piece gives strange results in my TableView. I want the UIImage displayed for the cells where the reprecented objects value for key "Marked" = "Yes".
What is the correct code for this?
if ([[[sortedObjects objectAtIndex: indexPath.row] valueForKey:#"Marked"] isEqual:#"Yes"])
{
cell.markedImageView.image = [UIImage imageNamed:#"markedItem.png"];
}

The problem is that you need to clear the imageView image each time the cell is reused.
- (void)configCell:(MyCustomCell *)cell atIndexPath:(NSIndexPath)indexPath
{
cell.markedImageView.image = nil;
// configure cell normally
if ([[[sortedObjects objectAtIndex: indexPath.row] valueForKey:#"Marked"] isEqual:#"Yes"])
{
cell.markedImageView.image = [UIImage imageNamed:#"markedItem.png"];
}
}

Related

UITableView design

I have UITableView where I want design as below.
For this I have images as below.
bottomRow.png
middleRow.png
topAndBottomRow.png
topRow.png
For this I have used below code inside -(UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIImage *selectedImage;
if (indexPath.row==0) {
selectedImage = [UIImage imageNamed:#"topRow.png"];
} else if (indexPath.row == ([products count]-1)) {
selectedImage = [UIImage imageNamed:#"bottomRow.png"];
} else {
selectedImage = [UIImage imageNamed:#"middleRow.png"];
}
if ([products count]==1) {
selectedImage = [UIImage imageNamed:#"topAndBottomRow.png"];
}
UIImageView *selectedBackgroundImageView = [[UIImageView alloc] initWithImage:selectedImage];
cell.selectedBackgroundView = selectedBackgroundImageView;
selectedBackgroundImageView = [[UIImageView alloc] initWithImage:selectedImage];
cell.backgroundView = selectedBackgroundImageView;
Now, everything works perfect.
BUT my designer is insisting on below point.
On tableview, I can have 4 cells at one time. Now let's say I have 6 rows.
Now when I have 6 rows (and tableview can show only 4), the 4th row shows bottomRow.png which is obvious. But my designer is insisting, even the tableview is scrolled, you should have same design for all 4 rows.
Edit 1
First of all, sorry for not being clear.
Well when the UITableView loads, I can only see first 4 cells even there are 6 cells because I have set the height of tableview accordingly. To see rest 2 cells, I have to scroll down. I believe this is how table view works.
Now let's say there are only 4 records. For 4 records, table view looks like image I have.
Now when I have tableview size as 6 (with id as 1-6), the fourth row gets image middleRow.png. Here what my designer wanted is to see bottomRow.png.
Now let's say I scroll down. Now I see row with cell id as 3-6. Now cell with id 3 have middleRow.png, but my designer wanted to see topRow.png.
I know this is ugly, but this is what my designer wanted to see.
Any suggestions to get this done?
One way to achieve your goal: Use numberOfRows to find out if this cell is the last cell.
In your cellForRowAtIndexPath:
if (indexPath.row==0) {
selectedImage = [UIImage imageNamed:#"topRow.png"];
.....
else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1){
selectedImage = [UIImage imageNamed:#"bottomRow.png"];
}
EDIT:
Sorry, I misunderstood your question, I have another proposal that I think you may try...
customCell, with a custom method to set its image. For example,
[customCell setSelectedImage: [UIImage imageNamed:#"middleRow.png"];
2.
In cellForRowAtIndexPath, you can set all cells to be: middleRow.png
3.
After loading of tableView, run a checking method using [self.tableView visibleCells];
eg
- (void) setImageForTopAndBottomCells{
CustomCell *topCell = [[self.tableView visibleCells] objectAtIndex: 0];
CustomCell *bottomCell = [[self.tableView visibleCells] objectAtIndex: self.tableView.visibleCells.count-1];
[topCell setSelectedImage: [UIImage imageNamed:#"topRow.png"];
[bottomCell setSelectedImage: [UIImage imageNamed:#"bottomRow.png"];
}
If your tableView is scrollable, set your ViewController as a UIScrollView delegate, in your delegate method scrollViewDidScroll, run the setImageForTopAndBottomCells method again.
There could be better ways for achieving what you want than the one I proposed, let me know if you found one.
What about using a combination of scrollViewDidScroll:, indexPathsForVisibleRows and reloadRowsAtIndexPaths:withRowAnimation: with something like this:
Every time the table view scrolls you get the list of visible rows using the UIScrollViewDelegate method scrollViewDidScroll:
If it scrolled enough to change the background, call the UITableView's reloadRowsAtIndexPaths:withRowAnimation: passing all the index paths that needs new background
Instead of using indexPath.row == 0 to find the top you would use [indexPath isEqual:[tableView indexPathsForVisibleRows][0]] and the same thing for the other rows
Hope this helps.
You can use middlerow.png as background view of your UITableViewCell in CellForRowAtIndexPath method. Below is the code
cell.backgroundView = [[UIImageView alloc] initWithImage[[UIImageimageNamed:#"middlerow.png"]stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0]];
And after this you can change the Corner radius (add border color/width) of your table view. But for this first you will have to add QuartzCore framework.
self.table.layer.borderColor=[[UIColor colorWithRed:209.0/255 green:209.0/255 blue:209.0/255 alpha:1.0] CGColor];
self.table.layer.borderWidth =3.0;
self.table.layer.cornerRadius =10.0;
Hope this helps.
You can Use this:
NSArray *visible = [tableView indexPathsForVisibleRows];
NSIndexPath *indexpath = (NSIndexPath*)[visible objectAtIndex:0];
-(NSArray *)indexPathsForVisibleRows returns an array of index paths each identifying a visible row in the receiver.So once you get the visible rows, you can use the required image according to indexpath.row.

UITableView cell image problem

I am trying to import an image in just cell number 1 and 2 ! , but I the result is my image will show in last cell ! I do not know why !! this is the picture that shows my situation :
// Configure the cell.
NSUInteger row = [indexPath row];
cell.textLabel.text = [titles objectAtIndex:row];
cell.detailTextLabel.text = [subtitle objectAtIndex:row];
switch (indexPath.row) {
case 0:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
case 1:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
}
return cell;
}
Either in your tableView:cellForRowAtIndexPath: set the imageView's image to nil before conditionally checking to set the new image or implement prepareForReuse on your cell subclass and set all of the cell's views values to nil.
This will ensure that reused cells are 'clean' before they're brought on screen.
Alternatively you could edit your switch to look like:
switch (indexPath.row) {
case 0:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
case 1:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
default:
cell.imageView.image = nil;
break;
}
The first thing that it makes me think of is that the first cell gets somehow recycled and used for the last cell. You can try to set the image view to nil for every cell and set it just in the first two cells. Should be something like this:
cell.imageView.image = nil;
Hope it helps! ;D
You might have used "static NSString *reuseIdentifier = #"Identifier" ", this means that all cells will be considered same by this reuseIdentifier. Only visible cells would be different so for example, if there are 5 visible cells on device, then only 5 new cells would be allocated for cell, and then if you scroll down or up, these 5 cells will be reused if you specified reuseIdentifier statically.
I would suggest to make cell uniquely identified by reuseIdentifier, change the above line to "NSString *reuseIdentifier = [NSString stringWithFormat:#"cell%d",indexPath.row]" This would solve the issue.
Hope this helps.
Your cells are reused by the tableview to save memory. You have to tell the cell not to use an image on every other cell. Modify the switch command like this:
switch (indexPath.row) {
case 0:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
case 1:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
default:
cell.imageView.image = nil;
break;
}
Sandro Meier
try this it might help you
case 0:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
case 1:
cell.imageView.image = [UIImage imageNamed:#"new.png"];
break;
default
cell.imageView.image=nil;

how to tag UIImage in UITableViewCell

I want to toggle UITableViewCell image - cell.imageView.image. (eg. Red <--> Green)
If the current image is green, the image suppose to change to Red when the user click the UITableViewCell.
Once I set the image
cell.imageView.image = [UIImage imageNamed:#"Green.png"];
How to detect which image is the cell currently using?
Thanks for any help!
Set the tag on the imageView itself:
#define IMAGE_TAG_GREEN 50
#define IMAGE_TAG_RED 51
-(UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {
static NSString *CELL_ID = #"some_cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CELL_ID];
if(cell == nil) {
//do setup here...
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CELL_ID] autorelease];
cell.imageView.tag = //some logic here...
}
if(cell.imageView.tag == IMAGE_TAG_GREEN) {
//...
} else {
//...
}
return cell;
}
Since tag is an inherited property from UIView, you cannot use it with UIImage itself, but you can use it with UIImageView
It's a bit crude, but you should be able to set up an if statement like the following:
if ([cell.imageView.image isEqual:[UIImage imageNamed:#"Green.png"]]) {
// image is green;
} else {
// image is red;
}
I tested it out just to make sure and it works fine
I believe just add a Boolean expression and make it TRUE if it is green and FALSE if it is red.
Make this boolean expression extern type so that this could be a global expression.
Set the boolean value on clicking the image.
I believe this would be of some help.
I'm new to this - but I imagine you could use an if/then statement.
If (cell.imageView.image = [UIImage imageNamed:#"Green.png"]) {
cell.imageView.image = [UIImage imageNamed:#"Green.png"];
} else
{
cell.imageView.image = [UIImage imageNamed:#"Red.png"];
}
Or you could go really fancy and use the ternary operator. Something like the following (note the code below is probably wrong - but should hopefully get you started!):
cell.imageView.image = ([UIImage imageNamed:#"Green.png"]) ?
cell.imageView.image = [UIImage imageNamed:#"Green.png"]; :
cell.imageView.image = [UIImage imageNamed:#"Red.png"];
Let us know how you go with this.
Kolya

Custom UITableViewCell imageView not updating after setImage

I've got a custom UITableViewCell class whose model object performs an asynchronous download of an image which is to be displayed in the cell. I know I've got the outlets connected properly in IB for WidgetTVC, I know that image data is being properly returned from my server, and I've alloc/init'd the widget.logo UIImage too. Why is the image always blank then in my tableViewCell? Thanks in advance.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Widget *theWidget = [widgetArray objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"WidgetCell";
WidgetTVC *cell = (WidgetTVC*)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"WidgetTVC" owner:self options:nil];
cell = self.widgetTVC;
self.widgetTVC = nil;
}
[cell configureWithWidget:theWidget];
return cell;
}
In my WidgetTVC class, I have the following method:
- (void)configureWithWidget:(Widget*)aWidget {
self.widget = aWidget;
self.nameLbl.text = aWidget.name;
[self.logoIvw setImage:aWidget.logo]; // logoIvw is the image view for the logo
}
Finally- I've got the callback method that sets the logo UIImage property on the Widget model object asynchronously (simplified):
(void)didReceiveImage:(ASIHTTPRequest *)request {
// I pass a ref to the Widget's logo UIImage in the userInfo dict
UIImage *anImage = (UIImage*)[request.userInfo objectForKey:#"image"];
UIImage *newImage = [UIImage imageWithData:[request responseData]];
anImage = newImage;
}
In didReceiveImage:, you're only modifying the local pointer anImage. You need to set the image property of your UIImageView in order to update what gets displayed. Instead of stashing a reference to your widget's UIImage, pass a reference to the UIImageView, and in didReceiveImage: do something like
UIImageView *imageView = (UIImageView*)[request.userInfo objectForKey:#"imageView"];
UIImage *newImage = [UIImage imageWithData:[request responseData]];
imageView.image = newImage;
Perhaps the best solution would be to have your model object have the image as a property and the display object subscribe to the image property's changes through KVO and update itself whenever the image property changes.
OK- there were a couple things wrong here. Thanks to bosmacs and Ed Marty as both of your comments were used to get to the solution.
First, I added a method to the Widget object to get the logo asynchronously:
- (void)asyncImageLoad {
...
// logo is a UIImage
[AsyncImageFetch fetchImage:&logo fromURL:url];
}
And my own AsyncImageFetch class looks like this:
+ (void)fetchImage:(UIImage**)anImagePtr fromURL:(NSURL*)aUrl {
ASIHTTPRequest *imageRequest = [ASIHTTPRequest requestWithURL:aUrl];
imageRequest.userInfo = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:anImagePtr] forKey:#"imagePtr"];
imageRequest.delegate = self;
[imageRequest setDidFinishSelector:#selector(didReceiveImage:)];
[imageRequest setDidFailSelector:#selector(didNotReceiveImage:)];
[imageRequest startAsynchronous];
}
+ (void)didReceiveImage:(ASIHTTPRequest *)request {
UIImage **anImagePtr = [(NSValue*)[request.userInfo objectForKey:#"imagePtr"] pointerValue];
UIImage *newImage = [[UIImage imageWithData:[request responseData]] retain];
*anImagePtr = newImage;
}
Finally, per Ed, I added this to the configureWithWidget method that helps set up my WidgetTVC:
[aCoupon addObserver:self forKeyPath:#"logo" options:0 context:nil];
And when a change is observed, I update the imageView and call [self setNeedsDisplay]. Works like a charm. Any way I can give you both points?

Updating imageView on UIButton within UITableViewCell

I have custom UITableViewCells (created in interface builder) which are used for a static UITableView which for the sake of argument I will call the AddUserTableViewController (i.e. I do not use autoreleased cells as I only have 5 rows).
In the top cell (used for the user name) I have embedded a UIButton which I use to open an UIActionSheet which in turn allows an UIImagePicker to set an image on the UIButton (i.e. [button.imageView.image = imageFromImagePicker]). The button has a default image (added in IB) which says "add image".
The image on the button is set without issue and remains in place even when I navigate to the detail page of any of the table cells with the exception of the user name cell which contains the button. When I select this cell the image dissapears and does not reappear once I navigate back to the AddUserTableViewController from the "add name" detail view. The "add image" default image, referred to above, is displayed.
I have tried many strategies amongst which have been:
1) using [self.tableView reloadData], [button.imageView setNeedsDisplay], [self.view setNeedsDisplay] in the viewWillAppear method;
2) using the above methods in the cellForRowAtIndexPath method;
3) using the above methods in the overriden willDisplayCell:forRowAtIndexPath: method;
When I place debugging NSLog statements in the program I can see that the button.imageView.image property is still set to the image selected using the UIImagePicker but it is not displayed (the default image from the nib is displayed).
As I mentioned above, this only happens if I navigate away from the AddUserTableViewController by selecting the UITableViewCell within which the UIButton is embedded.
I am currently at a loss as to what to do and would be extremely grateful for any assistance that anyone could offer. I just need to find a way to update the image on the embedded UIButton in the above-mentioned circumstances.
I've added the a section of the code from the cellForRowAtIndexPath: method just for illustrative purposes -
//populates the personal info section
if (section == kPersonalInfoAddSection) {
//Covers the add image button and the name adding field
if (row == kNameRow) {
UILabel *nameLabel = (UILabel *)[nameCell viewWithTag:kMainTextTag];
UILabel *reqLabel = (UILabel *) [nameCell viewWithTag:kSubTextTag];
//UIButton *imageButton = (UIButton *) [nameCell viewWithTag:kImageTag];
if (mainUser.imagePath != nil) {
UIImage *img = [UIImage imageWithContentsOfFile:mainUserImagePath];
imageButton.imageView.image = img;
[imageButton.imageView setNeedsDisplay];
//[imageButton setNeedsDisplay];
//[nameCell setNeedsDisplay];
NSLog(#"************************** Added the BESPOKE image (%#)to the image button", img);
}
else {
NSLog(#"************************** Added the DEFAULT image (%#)to the image button", addUserImage);
imageButton.imageView.image = addUserImage;
}
UIColor *blackText = [[UIColor alloc] initWithWhite:0 alpha:1];
NSString *firstName;
if (mainUser.firstName){
nameLabel.textColor = blackText;
firstName = mainUser.firstName;
}
else {
nameLabel.textColor = reqLabel.textColor;
firstName = NAME_STRING;
}
NSString *lastName = (mainUser.lastName)? mainUser.lastName : EMPTY_STRING;
NSString *name = [[NSString alloc] initWithFormat:#"%# %#", firstName, lastName];
nameLabel.text = name;
reqLabel.text = REQUIRED_STRING;
[blackText release];
return nameCell;
}
In the cellForRowAtIndexPath are you doing something that would 'unset' the image?