How can I customize the image displayed in different table view cells? - objective-c

I'm trying to add thumbnails into cells in UITableView
cell.imageView.image = [UIImage imageNamed: #"TestThumbnail.jpg"];
This is what i did in
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
method
However I want to add different thumbnails to each cell. Is it possible to do that?
If so, can I add name of each image(eg. "thumbnail.png") to .plist and use that to add thumbnails?
Thank you

It's definitely possible to do that. If you know which image you want to appear in each row ahead of time, one approach would be to construct an array of image file names. You could read that array from a property list, specify it directly in the code, download it from a server... whatever you like. Then, use the row property of the index path to select the image for the cell at that row:
// somewhere in your class declaration...
#property (retain, nonatomic) NSArray *filenames;
// somewhere in your initializer...
self.filenames = [NSArray arrayWithObjects:#"one.jpg", #"two.jpg", #"three.jpg", nil];
// in -tableView:cellForRowAtIndexPath:...
cell.imageView.image = [UIImage imageNamed:[self.filenames objectAtIndex:indexPath.row]];

Related

Setting Text Color on Static UITableViewCell

I have static cells and want to change text colour. I've made an outlet for the label. In the implementation i'm using
sine.textColor=[UIColor colorWithRed:191 green:48 blue:48 alpha:1.0];
In this case the text colour shows white. However if I use sine.textColor=[UIColor redColor]; it comes up red as expected. How?
Is there any way to change all text labels in one table view controller with one code (so i wouldn't need an outlet for every cell)?
1) UIColor requires a float from 0-1. (That really bugs me too) You can divide values by 255.0 like:
[UIColor colorWithRed:191.0f/255.0f green:48/255.0f blue:48/255.0f alpha:1.0]
In method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
set cell.textColor = [UIColor yourColor];
The way to do this for a STATIC cell is to create OUTLETS for all your cells, and change each individually... Otherwise you have to do this dynamically.
In your .h file:
#property (weak, nonatomic) IBOutlet UITableViewCell *myCell;
In your .m file
[self.myCell.textLabel setTextColor:[UIColor blackColor]];
For clarification the colour change should look like: cell.textLabel.textColor = [UIColor colorWithRed:191.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0]; (from UIColor forward you can put whichever RGB values your heart desires) thanks Tier
However -(UITableViewCell *)tableView:(UITableView) *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; doesn't work (for changing all cells' labels with one code ... maybe it's for DYNAMIC cells , however I'm looking for STATIC cells.

xcode ios: in cell image overlaps on the label

I am displaying an image on my cell in the table. I have the code within
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
While I am using storyboard, so I displayed the image in the cell with
cell.imageView.image = [UIImage imageNamed:_lotImagesArray[row]];
However, when I tried to load the image from a webserver, The image sits on top of the label in the cell (blocking the label text)
The code I used to display the image from webserver is this:
NSString *strURL = [NSString stringWithFormat:#"http://www.domainhere.com/images/%#", lotPhoto[row]];
NSURL *url = [[NSURL alloc] initWithString:strURL ];
cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
Can someone please advice where did I go wrong?
A couple of likely possibilities:
First, you might want to double-check to make sure that you have
cell.imageView.clipsToBounds = YES;
If you don't, when it sizes the image to fit in the UIImageView, the image can bleed over the bounds of the image view. I notice this problem, especially, when I'm doing this image loading in a background queue.
Second, if you're setting the imageView property of the UITableViewCell in the background (like the simplified sample code below), you should know that it's important to properly initialize the image with a blank image before you kick off the background image loading process. So, an example of very common code when loading a cell from a web based source is something like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = ... // you configure your cell however you want
// make sure you do this next line to configure the image view
cell.imageView.image = [UIImage imageNamed:#"blankthumbnail.png"];
// now let's go to the web to get the image
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
UIImage *image = ... // do the time consuming process to download the image
// if we successfully got an image, remember, ALWAYS update the UI in the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// let's make sure the cell is still visible (i.e. hasn't scrolled off the screen)
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell)
{
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.clipsToBounds = YES;
}
});
});
return cell;
}
Clearly, if you do something like that, you'll want to make sure that the [UIImage imageNamed:#"blankthumbnail.png"]; is not returning nil (i.e. make sure your app is successfully finding it in the bundle). Common problems might include failure to have a blank image at all, a mistake in the name, failure to include the image in your Target settings, under the "Build Phases" tab, under "Copy Bundle Resources".
Third, you need to make sure that when you're using subclassed UITableViewCell entries, that you don't use the standard UITableViewCell property names of imageView, textLabel, etc. Make sure to use your own, unique names. If you use imageView, the system gets confused between your new IBOutlet and the default imageView property of the UITableViewCell.

UITableViewCell strange behavior when on select changing an image inside

I have a problem while using a custom extended UITableViewCell with a nib file for a UITableView in my iPad application.
This cell have a behavior when selecting it to change a checkmark image from selected to unselected depended if it was selected, I use custom images for this and not the default check cell Apple have.
So everything in my functionality seems to be correct. I post some code.
I use the registerNib method to load the nib cell.
[tableView registerNib: [UINib nibWithNibName: #"ANibTableViewCell" bundle: nil] forCellReuseIdentifier: Identifier];
The nib cell is extended with a class file and managed through it, connecting outlets append model values etc.
In cellForRowAtIndexPath:
- (UITableViewCell*) tableView: (UITableView*) tableView cellForRowAtIndexpath: (NSIndexPath*) indexPath
{
ExtendedtableViewCell* cell;
AModel* model;
cell = [tableView dequeueReusableCellWithIdentifier: Identifier];
model = [modelForDisplay objectAtIndex: indexPath.row];
cell.model = model;
// Some operations setting the check mark if it needed etc.
// Checkmark is a UIImageView in the nib cell that just changes image on selection
// Some other operations happening notified by the model if selected or unselected
return(cell);
}
My problem is so strange now, lets say that you visually have 6 cells and you select the first 3, all fine, but if you scroll down to see the next cells, lets say you scroll 6 rows down you notice that always per 6 cells the 3 first looks selected, but the extended cell class instance which I keep if its selected or not is not in selected state. What visual effect is that?
Try this,
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *Identifier = [NSString stringWithFormat:#"cell%d.%d",indexPath.section,indexPath.row];
ExtendedtableViewCell* cell;
AModel* model;
cell = [tableView dequeueReusableCellWithIdentifier: Identifier];
model = [modelForDisplay objectAtIndex: indexPath.row];
cell.model = model;
// Some operations setting the check mark if it needed etc.
// Checkmark is a UIImageView in the nib cell that just changes image on selection
// Some other operations happening notified by the model if selected or unselected
return(cell);
}
hope it will helps you.....

update a UILabel when the cell in UITableView is selected

A really simple question here. I have a label on one view and a UITableView on the previous view. I have got a segue triggered when the user selects the row and I want the label to be updated with the text from that row. Here's one example, the code is pretty obvious.
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *countrySelection;
switch (indexPath.section) {
case kFirstSection:
countrySelection = [[NSString alloc]
initWithFormat:#"The country you have chosen is %#",
[self.MyCountries objectAtIndex: indexPath.row]];
[self performSegueWithIdentifier:#"doneResults" sender:self];
self.countryResult.text = countrySelection;
break;
The label isn't updated and I just don't know what should be done.
Thanks in advance!
These kind of things really need to be set on the View Controller that owns them. Use a public property to pass the value of the selected country to that view controller as outlined below:
First, create a property called something like:
#property(non atomic,strong) NSString *countryChosen;
in the destination View Controller, and make sure to #synthesize it
No reason to create another property for the IndexPath. Just use
// Pass along the indexPath to the segue prepareForSegue method, since sender can be any object
[self performSegueWithIdentifier:#"doneResults" sender:indexPath];
in the didSelectRowAtIndexPath method.
Then in the prepareForSegueMethod:
MyDestinationViewController *mdvc = segue.destinationViewController;
NSIndexPath *indexPath = (NSIndexPath *)sender;
mdvc.countryChosen = [self.MyCountries objectAtIndex: indexPath.row]];
On the viewDidLoad event of the Destination VC, just use:
self.countryResult.text = countryChosen;
* EDIT *
To deal with a datasource that has multiple sections, just use the same logic that you have in the cellForRowAtIndexPath.
NSDictionary *selRow = [[self.countriesIndexArray valueForKey:[[[self.countriesIndexArray allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:sindexPath.row];
Change this to suit your needs, but basically you are implementing the same logic that you would to display a cell, except you are specifying the indexPath (both section and row) that you want.
Then something like the following to set that property on the destination VC:
self.countryResult.text = [selRow valueForKey#"Country"];
In your current view controller create a new property for the indexPath of the cell the user selected, like this:
#property(strong,nonatomic) NSIndexPath *path;
#synthesize it and then when a user selects a row, set it by using
self.path = indexPath;
When you perform a segue, it will always call
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
So what you can do now when prepareForSegue: gets called, is the following:
/* if this is not the only segue you are performing you want to check on the identifier first to make sure this is the correct segue */
NSString *countrySelection = [[NSString alloc]
initWithFormat:#"The country you have chosen is %#",
[self.MyCountries objectAtIndex: self.path.row]];
segue.destinationViewController.countryResult.text = countrySelection;
/* after creating the text, set the indexPath to nil again because you don't have to keep it around anymore */
self.path = nil;
For this to work the view controller you want to show after selecting the cell must have a property for the UILabel, on which you are trying to set the text.

Retrieving cells in UITableView

I have a UITableView that once a cell is clicked, it pushes tableViewB, which contains customcells. These cells contain TextFields. Once the user does any updating, they click "Save", which then pops tableViewB and goes to the first UITableView. I would like to get all of the UITextField values from tableViewB when Save is clicked. What is the best way to go about doing that?
The problem is that I need to loop through all UITableView cells. I'm not sure how that is done or if it is even a good approach. Just looking for help on what is a good technique here.
in your tableViewB header, declare:
NSMutableArray *stringArray;
and in the implementation:
- (id) init { //whatever your tableViewB initializer looks like
if ([self = [super init]) {
//oldData is an NSArray containing the initial values for each text field in order
stringArray = [[NSMutableArray alloc] initWithArray:oldData];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
//Making the cell
[cell.textfield addTarget:self action:#selector(updateField:) forControlEvents:UIControlEventValueChanged];
....
//Setting up the cell
cell.textfield.tag = indexPath.row;
cell.textfield.text = [stringArray objectAtIndex:indexPath.row];
return cell;
}
- (void) updateField:(UITextField *)source {
NSString *text = source.text;
[stringArray replaceObjectAtIndex:source.tag withObject:text];
}
- (void) dealloc {
[stringArray release];
}
There are several ways you can choose to get your data back to the original table view, either by delegate, or by having the stringArray declared as a variable passed in to the tableViewB initializer rather than allocated there.
You should be aware that, in general, there are only about as many cell allocated as displayed on the screen. The cells that are not visible are actually not persistent but only get created when tableView:cellForRowAtIndexPath: is called. I suggest you create an array to cache the contents of all the text fields and which gets updated whenever a user leaves a text field (e.g. the textField:shouldEndEditing: method or something like that) is called.
If I understand your question - id each cell numerically and reference them in an array/climb the array to loop through them