I have a tableview that is blank by default. User can add cells to it.
I want the separator lines to be clear when there are no cells, and grey when there are cells.
I am using this code:
if ([[self.fetchedResultsController fetchedObjects] count] == 0)
{
self.routineTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.routineTableView.separatorColor = [UIColor clearColor];
}
else
{
self.routineTableView.separatorColor = [UIColor grayColor];
}
The problem is, when I launch the app with a blank table, and if I add cells, the grey lines are not there there until I restart the app. But if I start with cells there, then delete them, then re-add them, the lines are there. Any suggestions?
Maybe you are missing this?
...
else
{
self.routineTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; // or you have the previous 'None' style...
self.routineTableView.separatorColor = [UIColor grayColor];
}
EDIT :
You need this but not only this... According to Apple Documentation :
The value of this property is one of the separator-style constants described in UITableViewCell Class Reference class reference. UITableView uses this property to set the separator style on the cell returned from the delegate in tableView:cellForRowAtIndexPath:.
That means the style wont change for cells that are already loaded. Just scrolling the table to force cells to redraw should make separators appearing...
You then have to :
set it BEFORE cell is inserted
OR
reload tableView when the first cell is added
which is not easy to do with a NSFetchedResultsController, you should look into its delegate for a solution... or change direction, like hiding the tableView until you have a result maybe...
EDIT 2 : You can also simply add this :
[self.tableView reloadData];
but that's a dirty workaround that will just reload full tableView, losing most benefits of NSFetchedResultsController...
A quick fix I usually do is:
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([tableView respondsToSelector:#selector(setSeparatorStyle:)]) {
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
}
}
This changes the boolean flag of whether there will be a separator or not. Put this in viewDidLoad:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
And to make sure you've really made it go away, set the seperatorColor property to whatever the background color of the view and cell would be:
// If the background is white
self.tableView.separatorColor = [UIColor whiteColor];
So then even if somehow the above does not get called and the separator is still persisting - it would be the same color as what is behind it, therefore invisible.
Good luck.
Related
I want my tableView to show 6 rows with text in it, in this case "Example." As far as I can tell, I have my numberOfSectionsInTableView: and numberOfRowsInSection: set properly. See example code below:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// Return the number of rows in the section.
return 6;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"Example";
return cell;
}
The problem is when you see the image below showing lines for rows that shouldn't/don't exist.
How do I get rid of the lines showing past row 6?
The generally accepted way of doing this is to add a footer view with a frame size of CGRectZero, as such:
[tableView setTableFooterView:[[UIView alloc] initWithFrame:CGRectZero]]
What this does is tell the table that there is a footer, and so it stops displaying separator lines. However, since the footer has a CGRectZero as its frame, nothing gets displayed, and so the visual effect is that the separators simply stop.
Swift Version
The easiest method is to set the tableFooterView property:
override func viewDidLoad() {
super.viewDidLoad()
// This will remove extra separators from tableview
self.tableView.tableFooterView = UIView(frame: CGRect.zero)
}
This is Because of Your Table-view Height. Weather you have Write
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// Return the number of rows in the section.
return 6;
}
But its show rows According to Table-view Size. If you Dont want to show This extra Lines then Make UITableView Style Plain To Grouped.
Short and simple answer..
self.tableView.tableFooterView = [UIView new];
You could do something along the lines of:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:7 inSection:0];
[self.mytableView cellForRowAtIndexPath:indexPath].hidden = YES;
Im sure there are some better ways but this is the first thing that came to mind.
If you're referring to the light gray lines that appear below the last row, that's simply the default way a UITableView draws the row separator.
You could try changing the Separator style in Interface Builder (see the images below) to see if one of those might be more to your liking.
You didn't say what you do want to see past the last row. If you just want to see the window background, then just embed your table view in a UIView that's just tall enough to show the number of rows you want to see. If you want to see more rows without scrolling, then you would have to adjust the size of that containing view based on the number of rows.
To programmatically remove it, use this:
[yourTableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
It's a lot easier to:
return numberOfSections + 1
return 0 rows in the final section
This keeps it simple!
Two UITableViewCell related questions:
In my custom UITableViewCell I loop through an array (of which I do not know how many objects it holds) and add a UILabel displaying some text for each object in that array.
This means I have to adjust the height of the cell so that these labels fit in. How can I do this?
When going into edit mode, I have the cells indent, however I do not want this. I have tried the following:
cell.shouldIndentWhileEditing = NO;
and
-(BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
Both sadly failed, I have I no idea why. How could I possible remedy this?
Any help is much appreciated with either of these issues, thanks.
You can specify the height for every row with the delegate method [UITableViewDelegate tableView:heightForRowAtIndexPath:].
Just change what the method returns and the reload your table.
This method actually has nothing to do with the indendation of cell content:
Asks the delegate whether the background of the specified row should be indented while the table view is in editing mode.
You can try to set indentationWidth but I never managed to make it work.
Fortunately, it's easy to change everything you want in [UITableView layoutSubviews] method.
Example:
- (void)layoutSubviews {
[super layoutSubviews];
self.contentView.frame = self.bounds;
}
You may also need to set
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
{
return UITableViewCellEditingStyleNone;
}
For the dynamic height part there are plenty of other answers and a quick google found a tutorial here
I'm trying to make a UITableView like the native calendar app:
but I'm trying to learn the best way to do this. I'm able to get this for the most part with a switch statement in the cellForRowAtIndexPath method, but I'm having troubles changing the textColor when a cell is selected.
For some reason cell.isSelected is always NO, and I have no way to reload the tableview after another cell is selected anyway.
Should I subclass UITableViewCell for something this simple and store an array of cells?
Any help would be appreciated, thanks.
There is no need to subclass, as stated in the app doc the delegation function:
tableView:willSelectRowAtIndexPath:
should do the trick
EDIT:
Below you find some code that should demonstrate the idea of using the delegate. Please note that this code is untested, as i am currently not in front of my xcode.
-(void)willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (prevIndexPath != nil) {
UITableViewCell* prevCell = [self.tableView cellForRowAtIndexPath: prevIndexPath];
prevCell.textLabel.textColor = [UIColor black]; // your initial color here
}
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath: indexPath];
cell.textLabel.textColor = [UIColor green];
prevIndexPath = indexPath;
}
Make sure to set the UITableViewDelegate protocol to your controlling class that manages your TableView and set the tableViews.delegate to that.
To make this code run, you also have to define a property or variable with the name prevIndexPath. This ones holds the previously selected cell that is needed to revert to the cell to its initial color.
I have a bare-bones sample project here:
http://dl.dropbox.com/u/7834263/ExpandingCells.zip
In this project, a UITableView has a custom UITableViewCell. In each cell are 3 UIViews containing a label.
The goal is to expand the cell when tapped, then collapse it when tapped again. The cell itself must change it’s height to expose the subviews. Inserting or removing rows is unacceptable.
The demo project works almost as expected. In fact, in iOS 4.3 it works perfect. Under iOS 5, however, when the rows collapse, the previous cells magically disappear.
To re-create the problem, run the project in the simulator or device with iOS 5 and tap the first cell to expand it. Then tap the cell again to collapse it. Finally, tap the cell directly underneath it. The previous one disappears.
Continuing the tapping for each cell in the section will cause all the cells to disappear, to where the entire section is missing.
I’ve also tried using reloadData instead of the current setup, but that ruins the animations and feels a bit like a hack anyway. reloadRowsAtIndexPaths should work, but the question is why doesn’t it?
See images of what's happening below:
Table appears:
Cell expands:
Cell collapses:
Cell disappears (when tapping the cell underneath):
Keep repeating until the entire section disappears:
EDIT:
Overriding the alpha is a hack, but works. Here is another 'hack' that fixes it as well but WHY does it fix it?
JVViewController.m line 125:
if( previousIndexPath_ != nil )
{
if( [previousIndexPath_ compare:indexPath] == NSOrderedSame ) currentCellSameAsPreviousCell = YES;
JVCell *previousCell = (JVCell*)[self cellForIndexPath:previousIndexPath_];
BOOL expanded = [previousCell expanded];
if( expanded )
{
[previousCell setExpanded:NO];
[indicesToReload addObject:[previousIndexPath_ copy]];
}
else if( currentCellSameAsPreviousCell )
{
[previousCell setExpanded:YES];
[indicesToReload addObject:[previousIndexPath_ copy]];
}
//[indicesToReload addObject:[previousIndexPath_ copy]];
}
EDIT 2:
Made a few minor changes to demo project, worth checking out and reviewing JVViewController didSelectRowAtIndexPath method.
Your problem is in setExpanded: in JVCell.m, you are directly editing the frame of the target cell in that method.
- (void)setExpanded:(BOOL)expanded
{
expanded_ = expanded;
CGFloat newHeight = heightCollapsed_;
if( expanded_ ) newHeight = heightExpanded_;
CGRect frame = self.frame;
frame.size.height = newHeight;
self.frame = frame;
}
Update it to:
- (void)setExpanded:(BOOL)expanded
{
expanded_ = expanded;
}
Then remove the call to -reloadRowsAtIndexPaths:withRowAnimation: at line 163 of JVViewController.m and it will animate as expected.
-reloadRowsAtIndexPaths:withRowAnimation: expects different cells to be returned for the provided indexPaths. Since you are only adjusting sizes -beginUpdates & -endUpdates is sufficient to layout the table view cells again.
May be I am missing a point, but why dont you just use:
UITableViewRowAnimationNone
I mean instead of :
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
use
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationNone];
To animate the height changes of a tableView just call.
[tableView beginUpdates];
[tableView endUpdates];
Don't call reloadRowsAtIndexPaths:
See Can you animate a height change on a UITableViewCell when selected?
The cell that is fading out is the previous cell that is not changing size. As the documentation of reloadRowsAtIndexPaths:withRowAnimation: states:
The table animates that new cell in as it animates the old row out.
What happens is the opacity is set to 1 then immediately set to 0 and so it fades out.
If both the previous and the new cell change size then it works as intended. This is because the begin/end Updates notice the height changes and create new animations on those cells overriding the reloadRowsAtIndexPaths:withRowAnimation: ones.
Your problem is due to abusing reloadRowsAtIndexPaths:withRowAnimation: to resize the cells when it's intended for loading new cells.
But you don't need reloadRowsAtIndexPaths:withRowAnimation: at all. Just change the expanded state of the cells and do the begin/end updates. That will handle all the animation for you.
As a side note I found the blue selection a little annoying, in JVCell set the selectedBackgroundView to the same image as the backgroundView (or create a new image that has the correct look of a selected cell).
EDIT:
Move the statement adding previousIndexPath_ to indicesToReload to the if statement (at line 132) so that it is only added if the previous cell was expanded and needs to resize.
if( expanded ) {
[previousCell setExpanded:NO];
[indicesToReload addObject:[previousIndexPath_ copy]];
}
This removes the case where the previous collapsed cell would disappear.
Another option would be to set previousIndexPath_ to nil when the current cell is collapsed and only set it when a cell expands.
This still feels like a hack. Doing both the reloadRows and the begin/end Updates causes the tableView to reload everything twice but both seem to be needed to animate correctly. I suppose if the table is not too large this won't be a performance problem.
Short, pragmatic answer: Changing UITableViewRowAnimationAutomatic to UITableViewRowAnimationTop solves the issue. No more disappearing rows! (tested on iOS 5.1)
Another short, pragmatic answer, since UITableViewRowAnimationTop is said to cause its own issues: Create a new cell view instead of modifying the existing one's frame. In a real app the data displayed in the cell view is supposed to be in the Model part of the app anyway, so if properly designed it shouldn't be a problem to create another cell view which displays the same data only in a different manner (frame in our case).
Some more thoughts regarding animating the reload of the same cell:
UITableViewRowAnimationAutomatic seems to resolve to UITableViewRowAnimationFade in some cases, which is when you see the cells fading away and disappearing. The new cell is supposed to fade in while the old one fades out. But here the old cell and the new one are one and the same - So, could this even work? In the Core Animation level, Is it possible to fade out a view AND fade it in at the same time? Sounds dubious. So the result is that you just see the fade out. This could be considered an Apple bug, since an expected behavior could be that if the same view has changed, the alpha property wouldn't be animated (since it can't animate both to 0 and to 1 at the same time), but instead just the frame, color etc. would be animated.
Note the problem is just in the animation's display - if you scroll away and back, everything will appear correctly.
In iOS 4.3 the Automatic mode might have been resolved to something other than Fade which is why things work there (as you write they do) - I didn't dig into that.
I don't know why iOS chooses the Fade mode when it does. But one of the cases it does is when your code asks reloads a previously tapped cell, which is collapsed, and is different than the current tapped cell. Note the previously tapped cell is always reloaded, this line in your code is always called:
[indicesToReload addObject:[previousIndexPath_ copy]];
This explains the magic disappearing cells scenario you have described.
By the way, the beginUpdates/endUpdates seem like a hack to me. This pair of calls is just supposed to contain animations, and there aren't any animations you are adding in addition to the rows you already asked to reload. All it did in this case is magically cause the Automatic mode to not choose Fade in some cases - But this just obscured the problem.
A final note: I played around with the Top mode and found it can also cause problems. For example plugging the following code makes cells disappear funkily:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
Not sure if there is a real issue here (similar to the one with fading a view in and out at the same time), or maybe an Apple bug.
I just downloaded your project & found this section of code in didSelectRowAtIndexPath delegate where reloadRowsAtIndexPaths is used.
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView beginUpdates];
[tableView endUpdates];
instead of the above why don't you try this?
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
The reason i am suggesting this is that I believe reloadRowsAtIndexPaths:... only works when wrapped inbetween calls to:
- (void)beginUpdates;
- (void)endUpdates;
Outside of that, behavior is undefined and as you've discovered, fairly unreliable. Quoting relevant part of "Table View Programming Guide for iPhone OS":
To animate a batch insertion and deletion of rows and sections, call the insertion and deletion methods within an animation block defined by successive calls to beginUpdates and endUpdates. If you don’t call the insertion and deletion methods within this block, row and section indexes may be invalid. beginUpdates...endUpdates blocks are not nestable.
At the conclusion of a block—that is, after endUpdates returns—the table view queries its data source and delegate as usual for row and section data. Thus the collection objects backing the table view should be updated to reflect the new or removed rows or sections.
The reloadSections:withRowAnimation: and reloadRowsAtIndexPaths:withRowAnimation: methods, which were introduced in iPhone OS 3.0, are related to the methods discussed above. They allow you to request the table view to reload the data for specific sections and rows instead of loading the entire visible table view by calling reloadData.
There could be other valid reason but let me mull on this a bit, since i have your code too I could muck around with it. Hopefully we should figure it out...
When you use this method, you have to be sure that you are on the main thread.
Refreshing a UITableViewCell as follow should do the trick :
- (void) refreshTableViewCell:(NSNumber *)row
{
if (![[NSThread currentThread] isMainThread])
{
[self performSelector:_cmd onThread:[NSThread mainThread] withObject:row waitUntilDone:NO];
return;
}
/*Refresh your cell here
...
*/
}
I think you should not retain the previous indexPath when the cell is not expanded,
try by modifying you did select method like the below, its working fine..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL currentCellSameAsPreviousCell = NO;
NSMutableArray *indicesToReload = [NSMutableArray array];
if(previousIndexPath_ != nil)
{
if( [previousIndexPath_ compare:indexPath] == NSOrderedSame ) currentCellSameAsPreviousCell = YES;
JVCell *previousCell = (JVCell*)[self cellForIndexPath:previousIndexPath_];
BOOL expanded = [previousCell expanded];
if(expanded)
{
[previousCell setExpanded:NO];
}
else if (currentCellSameAsPreviousCell)
{
[previousCell setExpanded:YES];
}
[indicesToReload addObject:[previousIndexPath_ copy]];
if (expanded)
previousIndexPath_ = nil;
else
previousIndexPath_ = [indexPath copy];
}
if(currentCellSameAsPreviousCell == NO)
{
JVCell *currentCell = (JVCell*)[self cellForIndexPath:indexPath];
BOOL expanded = [currentCell expanded];
if(expanded)
{
[currentCell setExpanded:NO];
previousIndexPath_ = nil;
}
else
{
[currentCell setExpanded:YES];
previousIndexPath_ = [indexPath copy];
}
// moving this line to inside the if statement blocks above instead of outside the loop works, but why?
[indicesToReload addObject:[indexPath copy]];
}
// commenting out this line makes the animations work, but the table view background is visible between the cells
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
// using reloadData completely ruins the animations
[tableView beginUpdates];
[tableView endUpdates];
}
This problem is caused by returning cached cells in cellForRowAtIndexPath.
The reloadRowsAtIndexPaths is expecting to get fresh new cells from cellForRowAtIndexPath.
If you do that you will be ok ... no workarounds required.
From Apple doc:
"Reloading a row causes the table view to ask its data source for a new cell for that row."
I had a similar issue where I wanted to expand a cell when a switch is activated to display and extra label and button in the cell that is normally hidden when the cell is at its default height (44). I tried various versions of reloadRowsAtPath to no avail. Finally I decided to keep it simpler by adding a condition at heightForRowAtIndexPath like so:
override func tableView(tableView: UITableView,heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if ( indexPath.row == 2){
resetIndexPath.append(indexPath)
if resetPassword.on {
// whatever height you want to set the row to
return 125
}
}
return 44
}
And in whatever code you want to trigger the expanding of the cell just insert tableview.reloadData(). In my case it was when a switch was turned on to indicate the desire to reset a password.
#IBAction func resetPasswordSwitch(sender: AnyObject) {
tableView.reloadData()
}
There is no lag with this approach, no visible way to see that the table reloaded and the expansion of the sell is done gradually like you'd expect. Hope this helps someone.
#Javy, i noticed some weird behavior while testing your app.
While running on iPhone 5.0 simulator the previousIndexpth_ variable is of
class NSArray (it looks like.) here is the debugger output
(lldb) po previousIndexPath_
(NSIndexPath *) $5 = 0x06a67bf0 <__NSArrayI 0x6a67bf0>(
<JVSectionData: 0x6a61230>,
<JVSectionData: 0x6a64920>,
<JVSectionData: 0x6a66260>
)
(lldb) po [previousIndexPath_ class]
(id) $7 = 0x0145cb64 __NSArrayI
Whereas in iPhone 4.3 simulator it is of type NSIndexPath.
lldb) po [previousIndexPath_ class]
(id) $5 = 0x009605c8 NSIndexPath
(lldb) po previousIndexPath_
(NSIndexPath *) $6 = 0x04b5a570 <NSIndexPath 0x4b5a570> 2 indexes [0, 0]
Are you aware of this issue? Not sure whether this will help but thought of letting you know.
Try this hope it will help u Cell Expansion
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.