Customize TableviewCell depending on section - objective-c

How do I customize the background image of a UITableViewCell depending on the section, they are in? E.g. in section one, the cells are supposed to have a green .png image as a background image, whereas in section two, the cells are supposed to have a red .png image as background.

See Populating the Table View With Data for how to access and use section information.
When you have more then one section you implement some optional table view source methods to deal with sections.
Then when you create cell, check in which section it is and set it up accordingly, in:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath;
In this method you can access indexPath.section and format your cell.
See Table View Programming Guide for more.
UIKit adds property section to NSIndexPath so you can get section from index path passed in to the above method (see the first example I linked).

example:
if(section == 0) {
background.image = [UIImage imageNamed:#"green.png"];
}
else if(section == 1) {
background.image = [UIImage imageNamed:#"blue.png"];
}

Related

In UITableViewCell, UIImageView content repeats after some cells using AFNetworking

The content is distinct on all the cells on the first page but as we scroll down, only the UIImageView is repeated though the UILabels are distinct.
I am using [UIImageView setImageWithURL:(NSURL *)url] from AFNetworking which was included in the RestKit. Heres the implementation
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RClubTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"RClubTableViewCell"];
RClubObject * club = _clubs[indexPath.row];
[cell.clubImageView setImageWithURL:[NSURL URLWithString:club.clubImageURL]];
cell.nameLabel.text = club.clubName;
return cell;
}
Seems like iOS is somehow using the previously created cells. Would like to have completely fresh cells while scrolling.
You need to call setImageWithURL:placeholderImage: with a non-nil placeholder image to have the old image removed from the image view.
I guess you missed reallocation in your cellForRowAtIndexPath:
Your code should be something like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RClubTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"RClubTableViewCell"];
if(cell == nil)
{
cell = [[RClubTableViewCell alloc] init];
}
RClubObject * club = _clubs[indexPath.row];
[cell.clubImageView setImageWithURL:[NSURL URLWithString:club.clubImageURL]];
cell.nameLabel.text = club.clubName;
return cell;
}
Update :
Okay. I just had the same issue. Here what my search over google tells me : Since you are downloading the image in async and also scrolling, it gets downloaded and attached to other cells which are currently visible
Solution:
add tag to each imageView using indexpath.row
Use function setImageWithURL: placeholderImage:success:
In success block reload the cell using the tag value.
Though I haven't tested this I feel this should work. PS : Let me know if this works I also would have to do the same then :)
Yes, iOS is reusing the previously created cells. That is what this line of code does, so that the app does not have to spend the time creating a new cell from scratch:
RClubTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"RClubTableViewCell"];
Clear the image from the recycled cell before adding the new image for this cell:
cell.clubImageView.image = nil;
[cell.clubImageView setImageWithURL:[NSURL URLWithString:club.clubImageURL]];
cell.nameLabel.text = club.clubName;
return cell;
Alternatively, you could create a new cell from scratch instead of dequeuing one.

UITableView checkmark in some particular row in every section

I have a UITableView containing 'N' number of sections with 'N' no of rows in each section.
My requirement is:
When the table view page loads the 1st row in each section must be check-marked. The user then will have the option to select his choice in each section and that row in that particular section is check-marked.
How do I implement this functionality?
The information displayed in any particular row of a table is determined by the table's data source. Make sure that the data structure that you use for your data has some way of indicating that a given row has a check mark. Then just implement -tableView:cellForRowAtIndexPath: such that it determines whether a check mark should be displayed for the cell in question and adjusts the cell accordingly.
For example, let's say that the data is represented as an array of sections, and each section is an array of dictionaries. Each row, then, has its own dictionary. If a row is to have a check mark, its dictionary will have a checked entry set to YES; if it doesn't, that entry is NO. You can display the check mark as an image. Then you have:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyTableViewCell *cell = ... // code to get the cell
if (myData[indexPath.section][indexPath.row][#"checked"].boolValue == YES) {
cell.checkedImageView.image = self.checkmarkImage;
}
else {
cell.checkedImageView.image = nil;
}
return cell;
}
Putting the check mark in the first row of each section is just a matter of initializing your data so that the first entry in each section's array is checked and the others aren't.
You can change the checked cell by implementing -tableView:didSelectRowAtIndexPath: so that it scans through the array for the given section and unchecks any checked row, and then checks the selected row.
Of course, you don't have to represent your data using an array of arrays of dictionaries, and there's a good chance that you don't. That's fine -- the point here is just that you'll implement the functionality that you're after by implementing the table's delegate and data source such that they support the check mark, and that the presence or absence of the check mark in any particular row will be determined by some aspect of your table's data.
You can set your cell's accessoryType to a checkmark:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ... // code to get the cell
// isCellSelectedAtIndexPath: is your custom method
// which encapsulates cell selection state logic
if ([self isCellSelectedAtIndexPath:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}

Updating subviews in cells on a UITableView

I'm developing an application in iPad 6.0 using Storyboards.
Let me first explain my goal. I'm trying to achieve a Master-Detail (SplitViewController-like) View Controller using 2 UITableViewControllers.
The first UITableView("Master"), let's call this HeaderTableView, as the name implies, lists down the Headers for the...
...Second UITableView("Detail"), let's call this the EncodingTableView, which contains a programmatically changing CustomTableViewCell (subviews contained within each cell may be a UITextField, UIButton or UISwitch).
See EncodingTableView.m
- (void)updateEncodingFields:(NSArray *)uiViewList
{
// Add logic for determining the kind of UIView to display in self.tableView
// Finally, notify that a change in data has been made (not working)
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *encodingFieldsTableId = #"encodingFieldsTableId";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:encodingFieldsTableId];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:encodingFieldsTableId];
}
// Change text in textView property of CustomTableViewCell
cell.encodingFieldTitle.text = uiViewList.title;
// added methods for determining what are to be added to [cell.contentView addSubView:]
// data used here is from the array in updateEncodingFields:
}
My HeaderTableView.m, contains the didSelectRowAtIndexPath to update the EncodingTableView
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (![selectedIndexPath isEqual:indexPath]) {
selectedIndexPath = indexPath;
[self updateDataFieldTableViewForIndexPath:indexPath];
}
}
- (void)updateDataFieldTableViewForIndexPath:(NSIndexPath *)indexPath {
[self.encodingTableView updateEncodingFields:self.uiViewList];
}
Question
- Data is all ok but why doesn't EncodingTableView "redraw"ing the fields? My
suspicion is that reusing cells has something to do with this but I just can't figure out why.
Screenshots on the result:
Initial Selection in HeaderTableView
Second Selection in HeaderTableView
What I've tried :
I kept seeing suggestions such as [UITableView setNeedsDisplay],
[UITableView reloadData] and [UITableView setNeedsLayout] but none of
them worked.
Removing the reuse of tableViewCells works fine but this causes parts of my
CustomTableView.encodingFieldTitle to disappear. Not to mention that this might cause performance issues if I were to drop reusing cells.
Restrictions:
I know that a good idea is to use a SplitViewController but this is just a subpart of my app (hence not the RootViewController).
Finally, thanks for reading such a long post. ;)
It looks like you are most likely adding subviews inside tableView:cellForRowAtIndexPath:.
The issue is that if you use cell reuse then are not always starting from a blank slate inside tableView:cellForRowAtIndexPath: instead you can possibly be given a cell back that has already been configured once. This is what you are seeing, a cell that has previously had labels added to it is handed back to you and then you add some more labels over the top.
There are a few way to deal with this:
(My preferred option) Create a subview of UITableViewCell with these extra sub views available as properties.
Ensure the cell setup is only done once
A great place to do this is when you actually create a cell when one does not already exist e.g. inside the if (cell) check
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:encodingFieldsTableId];
// add subview's here and give them some way to be referenced later
// one way of doing it is with the tag property (YUK)
UILabel *subView = [[UILabel alloc] initWithframe:someFrame];
subView.tag = 1;
[cell.contentView addSubview:subView];
}
UILabel *label = (id)[cell.contentView viewWithTag:1];
label.text = #"some value";
One problem i can see in your code is that the cell identifiers used are different in tableView cellForRowAtIndxPath function.
While dequeueing you are using this identifier - > "encodingFieldsTableId"
&
while creating a cell you are using this identifier - > "dataFieldUiGroupTableId".
Ideally these two identifiers should be same !!!
Try adding,
cell.encodingFieldTitle.text = nil;
Before if(cell == nil)
So that whenever your cellForRowAtIndexPath method is called, the string already present in the cell you are going to reuse will get deleted and the new text in uiViewList.title will be displayed.

How to make UITableView look like the one in Contacts?

I'm trying to make UITableViewController look like following.
(it has picture and several rows for someone's identify.)
I wonder how to make like following programmatically.
How to adjust UITableViewCell's origin.x and width?
How to add a picture at left top?
Please help me.. I will thank you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier];
cell.frame = CGRectMake(50, 0, 250, 44) <--- ?????? I think this is wrong way.
return cell;
}
My best bet is that either there are two static UITableViews inside a UIScrollView or that it's some custom subclass UIView set as tableHeaderView and styled to look as on the picture. If I were to implement it I'd go with the second choice.
Make a subclass of UITableView. Give your subclass properties referring to the photo well and the three special row cells.
Override layoutSubviews to call [super layoutSubviews] and then set the frames of the photo well and the three special row cells.
The photo well should not be a cell.

table view data loading issue

I have a doubt in table view. I have placed a label & switch in table view cell. I set the switch value as NO by default. Now when table view is loaded in simulator the table view displays switch with NO value. Now I selected switch value as YES. But table view uses dequeue reusable cell method Property when table view is scrolled objects will reload every time now what will be the switch value will it be NO or YES?
It will be YES.
One more thing on scrolling tableview it not call reload method. Its just reusing already created tableview cells if you are using deque reusable cell method Property.
TableViewCells get destroyed and created where necessary when the table view gets scrolled.
When a cell gets destroyed as it goes out of the visible screen area, your switch control being a subview of the cell also gets destroyed.
So when you scroll back to one of your previously set switches, what you're actually seeing is another instance of a UITableViewCell with a switch view added to it, and so it looks like the switch value changed back to NO.
What you need is a third thing that remembers what the value of each switch should be in each row. If you're display a table of Core Data entity information, then perhaps you can define a property for your entity like "active". In that case, every time you change a switch value, you set your core data entity "active" property to the switch value e.g.:
-(UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if(cell == nil)
{
// set switch control tag number (don't use 0)
}
// get switch control by tag number
// pseudocode
Engine *myEngine = [arrEngine objectAtIndex:indexPath.row];
mySwitchControl.active = myEngine.active;
...
}
// when you change switch value, remember to update your core data entity value
-(void)updateSwitchValue:(BOOL) newValue
{
// update value
}
Otherwise, you can simply use a NSMutableArray of bool values to identify which row each switch should be YES or NO:
// my header file (.h file)
#interface
{
NSMutableArray *arrSwitchValues;
}
// my implementation file (.m file)
-(UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if(cell == nil)
{
// set switch control tag number (don't use 0)
}
// get switch control by tag number
// pseudocode
BOOL switchVal = [arrSwitchValues objectAtIndex:indexPath.row];
mySwitchControl.active = switchval;
...
}
// when you change switch value, remember to update your array
-(void)updateSwitchValue:(BOOL) newValue
{
// update value
}
Hope that helps.
to guarantee not have duplicated cells:
use this code in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
as follows :
for(UIView *v in [cell subviews])
{
if([v isKindOfClass:[UILabel class]] ||[v isKindOfClass:[UISwitch class]])
[v removeFromSuperview];
}