I'm sure this is some easy-to-fix issue that I've missed, but I can't figure it out. I've got a grouped table view with 3 sections. I'm using the following code to generate section headers:
-(NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
NSString *header = #"Header 1";
return header;
}
if (section == 1) {
NSString *header = #"Header 2";
return header;
}
else {
NSString *header = #"Header 3";
return header;
}
}
When my table is displayed, there are two headers for each section - one with white text on a gray bar that stretches across the screen (like the letter separators in the Contacts app), and one in gray text on the table background (which is the one I want). Both headers have identical text. Where is the first header coming from?
The code you have presented looks completely normal (though it probably is generating a warning for not having a return null; at the end. The issue is somewhere else, but there's no way to determine what that is with what you've given.
Related
Here i need to hide the phone number, email , birthDate, anniversary date and other labels in case there is no values for those fields. How can i do this?
Many ways, starting with the simplest:
self.emailLabel.hidden = YES;
But you probably want to reformat the other parts of the view to fit the empty space. Keeping it simple, you would then do something like this:
self.phoneLabel.frame = CGRectOffset(self.phoneLabel.frame, 0, -self.emailLabel.bounds.size.height);
... and so on for anything below. But you can see how this would become tedious. The next and probably best alternative is a UITableView that adjusts it's section count based on whether some of that data is present. That would go like this. Prepare a mutable array of arrays with the parts of your model and their values.
- (void)prepareModel {
self.model = [NSMutableArray array];
[self.model addObject:#[#"Name", #"Judy"]; // get "Judy" from your data
if (/* model has email */) {
[self.model addObject:#[#"Email", #"judy#gmail.com"]; // get email from your model
}
// and so on for conditional parts of your model
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.model.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
return self.model[section][0];
}
And the cellForRow would init the cell using self.model[section][1].
What you can do is simply hide the UILabel's if the value for the NSStrings that you are putting them in is NULL/nil .
NSString *labelString;
if([labelString length]>0)
{
}
else
Label.hidden = YES;
It is probably a better idea to use a UITableView to do this, by putting the labels in rows of the tables. If the labels are empty, you can delete the table rows and iOS will dynamically resize the table height for you.
I'm a newbie to iPhone development. I have a table view with multiple sections in it. I'm changing the color of cells like this and it works fine.
if ([indexpath row]%2)
{
trackCell.contentView.backgroundColor = [UIColor clearColor];
}
else
{
trackCell.contentView.backgroundColor = [UIColor colorWithRed:212/255.0 green:212/255.0 blue:212/255.0 alpha:0.1];
}
But now the last cell from one section has the same color as the first cell in the next section. How can I solve this?
This is pretty dirty, but you could count up all the cells before your current one and then use that count to work out the required color. This is untested, but something like the following should do it:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int cellCount = 0;
for (int i=0;i<indexPath.section-1;i++)
{
cellCount+=[self numberOfRowsInSection:i]
}
cellCount+=indexPath.row;
if(cellCount%2==0)
{
//set one color
}
else
{
//set other color
}
// blah
}
the problem is that if cell is in section 1 (or 2, 3, ...)
and the previous section has an odd number of cells, it ends with the same color of the last cell of previous cell.
so, you need to check the previous section number of cells, and if that number is odd, invert your "if" statement, and leave it as it is now if it is even
EDIT:
int toBeAdded = 0;
if (indexPath.section>0) {
toBeAdded = ([self tableView:tableView numberOfRowsInSection:(indexPath.section -1)]) %2 ;
}
if (([indexpath row]+toBeAdded)%2) {
trackCell.contentView.backgroundColor = [UIColor clearColor];
} else {
trackCell.contentView.backgroundColor = [UIColor colorWithRed:212/255.0 green:212/255.0 blue:212/255.0 alpha:0.1];
}
EDIT 2:
seeing "Will Jenkins"... he's right... you need to see all previous sections, not just the previous one...
his way to count all cells in a section is not so good and fast as mine, but his answer is the right one, +1 for him... anyway, the best way could be to combine his loop and my call to tableView:tableView numberOfRowsInSection:
Regaridng section change color, need to write your own logic like,
Need to use Static int value irrespective of sections and use already using code with replacing
indexpath.row with your value. i.e.
Static int Index;
if ( Index % 2)
{
trackCell.contentView.backgroundColor = [UIColor clearColor];
} else {
trackCell.contentView.backgroundColor = [UIColor colorWithRed:212/255.0 green:212/255.0 blue:212/255.0 alpha:0.1];
}
Index++;
It happens due to your Number of Rows in each section...
Suppose you are trying to provide RED color to Odd Rows and GREEN color to Even Rows and you have 3 rows in First Section then last cell will have RED color and First cell of Second Section also has RED color.
So you just need to check the number of rows in Previous Section. If it is Even Number then you should Maintain the Order of Color , otherwise simplly Change the Order of Color for the Section.
I am using grouped tableview for developing a contact list using database. I have to show the message "No Contacts" on tableview when there is no contact in list. how can I do it?
Share your ideas..
Thanks in Advance
supposing that you are using an array to store all the contacts then use the following delegate
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// You can also modify this condition according to a specific section
if([YOUR_ARRAY count] == 0)
{
return 1;
}
else
return [YOUR_ARRAY count];
}
Now adding data to table in following delegate
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialise your cell
if([YOUR_ARRAY count] > 0){
// add your array data to cells
}
if([YOUR_ARRAY count] == 0){
// this means no contacts in array and therfore you have only one cell to display NO CONTACTS
}
return cell;
}
For cases like this one we used table headers.
If the table had elements in his data source, the table header was clear and had a 1px height.
If the data source had no elements, then the table header view was set as big as the table's frame and contained a message, an image or whatever you might need.
The functions (table view delegate methods, actually) we used were height for header in section and view for header in section. We verified the data source inside the viewForHeader function
You can achieve the same effect using the table footers as well
you can add UILabel
ande set the text of the label
label.text = #"No results ";
and you make a test
if ([contacts count] == 0)
{
yourTableview.hidden = YES;
yourLabel.hidden = NO;
}
else
{
yourTableview.hidden = NO;
yourLabel.hidden = YES;
}`
This is related to another question of mine which wasn't answered in a helpful way (message when a UITableView is empty).
I'm trying to show an UIImage graphic that says You haven't saved any bookmarks over an UITableView when it's empty. I have NSNotification set-up so that when bookmarks are added or deleted, a message is sent so that the UITableView can be updated.
I've been trying to do it with this code. Why won't this work?
- (void)bookmarksChanged:(NSNotification*)notification
{
[self.tableView reloadData];
UIImageView* emptyBookmarks = [[UIImageView alloc] initWithFrame:CGRectMake(75, 100, 160, 57)];
emptyBookmarks.alpha = 1;
emptyBookmarks.image = [UIImage imageNamed:#"emptyBookmark.png"];
[self.view addSubview:emptyBookmarks];
[emptyBookmarks release];
if ([self.dataModel bookmarksCount] == 0)
{
emptyBookmarks.alpha = 1;
}
else
{
emptyBookmarks.alpha = 0;
}
}
I'm probably approaching this the wrong way... But if salvageable, what am I doing wrong?
When I initially have an empty bookmarks tableview, there's no image displayed. After I add a bookmark and then delete it, the image shows. Grrh.
Another way (and IMO the correct way) to do this is to manipulate the backgroundView property on the UITableView.
While making a single cell with a custom image cell would certainly works, I think it overly complicates the logic of your UITableViewController's data source. It feels like a kludge.
According to UITableView documentation:
A table view’s background view is automatically resized to match the
size of the table view. This view is placed as a subview of the table
view behind all cells , header views, and footer views.
Assigning an opaque view to this property obscures the background color
set on the table view itself.
While you probably don't want to just set it to your UIImageView, it is very easy to make a UIView that contains the UIImageView that you want.
Well first off if you were going to do it that way, you would need to reload the tableView after updating the image or model etc. and not before.
But you are probably making things more complicated than they need to be!
Why not just check to see if the data for section 0 and indexPath.row 0 are empty and if so in cellForRowAtIndexPath display a text message accordingly.
// First make sure there is always one row returned even if the dataModel is empty.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger numRows = 0;
if ([self.dataModel lastObject]) {
// Return the number of rows in the section.
numRows = [self.dataModel count]; // etc.
}
if (numRows < 1) numRows = 1;
return numRows;
}
// Then display the data if there is some, otherwise a message if empty.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if ([self.dataModel lastObject]) {
// setup the cell the normal way here.
} else { // the datasource is empty - print a message
cell.textLabel.text = nil;
cell.detailTextLabel.text = NSLocalizedString(#"You haven't saved any bookmarks", #"");
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.7];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Are you sure [self.dataModel bookmarksCount] is equal to 0 ?
While I agree that you are probably going about this the wrong way,
your image is allocated and added in your bookmark changed, your notification does not trigger when there are no bookmarks initially. Hence you don't see the image. Call the bookmar changed when your table view inits or appears.
Probably the best way to achieve this is to perform a check in your numberOfRowsInSection method to return 1 if your data source is empty. Then in cellForRowAtIndexPath check if your data source is empty and if it is, create a custom cell that contains whatever you want. In heightForRowAtIndexPath you need to return your custom cell height if your datasource is empty, but only if you want the cell larger than the default. At least that is how I would approach it.
when bookmarks count is nil add one to your row method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
int c;
c = bookmarks.count;
if(c == 0){
c = 1;
}
return c;
}
and then the same check again in your cellforrowatindexpath.
Another thing to be aware of in this situation is that if you're using core data and you're datasource is feeding off an entity, you will want to make sure your model matches. You can get some weird side-effect behavior in certain situations. This is especially true if you allow editing and core data has an empty model but you're tableview is still showing a cell.
I have some VERY simple code to return the title for a section header:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section==0) {
return #"";
} else if (section==1) {
return #"Actions";
} else if (section==2) {
return #"Attached To";
}
return #"";
}
For some reason when the headers are actually displayed on the simulator, half of the time they're simply the first letter and then ellipses. Scrolling up and down (to refresh the header view most likely) will result in the title showing correctly roughly half the time and showing incorrectly the other half of the time.
Do anyone have any idea what could be causing this? I think this is more of a recent development, but it seems to happen in almost all UITableViews in my application. I don't want to say this is a 3.2 issue, but it might have started happening around then, but either way it must be related to the code somehow. Thank you.
I've figure it out: the actual problem with the code was returning #"". If you return just a blank string, instead of nil, it will cause a problem with the display of headers and footers.
You need to instead return a nil string to get all headers and footers to display correctly. Returning a space #" " will still leave the vertical space for the header so that is not a viable option. I've changed all instances of return #""; to simply return nil;
i copy&pased your code to one of my projects and it works flawless. (sdk 3.2.1)
Maybe the error is in another part?
Are creating your own tablecells? If so, are you returning the apropiate height from "tableView:heightForRowAtIndexPath:"?
(that problem did hit me once)
When setting the Section Header Titles, I have better success in using an empty NSString that gets set to the corresponding Section, and then later release that string when completed; as well as limiting my use the nested If()Else() statments.
I try to keep it simple and clean. Of course for those tables where I have more than 3 sections, I use a "Switch" statement in place of the If() statements.
The great thing about this function is that it gets called as many times-(number of sections) that you have and will run through the code each time. The NSString *sectionHeader=nil; gives the compiler a value to be returned, regardless of what is embedded within your If() statements. Otherwise, you get warnings because the compiler doesn't search within the If() statements for your return value.
You can also initialize the String to a "Default" value, e.g. NSString *sectionHeader = #"Default Header Title";. If non of the If() statements are satisfied, then the allocated default header value will remain the same throughout the function and thus get returned as sectionHeader for the Title.
Basic Structure Below:
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
//TEMP SECTION STRING HOLDER:
NSString *sectionHeader = nil;
//SET TITLE FOR EACH SECTION:
if(section == 0) {
sectionHeader = #"Section Header No. 1";
}
if(section == 1) {
sectionHeader = #"Section Header No. 2";
}
if(section == 2) {
sectionHeader = #"Section Header No. 3";
}
//RETURN THE SECTION HEADER FOR EACH SECTION:
return sectionHeader;
}