In this project I have absolutely no code. In my main.storyboard I have a TableViewController with so far 1 cell. In that one cell I put an Image View in, then I selected the certain picture. The cell is 320 (Width) by 44 (Height). Everything seems fine in the main.storyboard, however I press run, the app opens but there is nothing there, only a bunch of lines.
Any help would be great I will give screenshots to anyone who needs them in order to help me solve this problem. I am using xCode 5.1
If you don't want to write any code than you must tableView type to static!
Check that.
Here's the snippet for TableViewDelegate. Hope this will help. Don't forget to thumbs up
Make sure you have this in your TableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1; ---->> should return 1
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10; ----->> return how many rows you want to show, mostly you write
return yourarray.count;
}
I think the problem will be in the method below
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil; ---->> Instead of UITableViewCell you need to
change to the class name of the
TableCell ( This is where your cell is
created)
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"Cell"]; ---->>Instead of UITableViewCell you need to
change to the class name of the
TableCell ( This is where your cell is created)
}
cell.textLabel.text = #"Cell";
return cell;
}
You have to use either a static tableview that uses predefined cells or (by default) use a dynamic tableview - in that case you have to provide the cells in code by adhering to the tableviews data source protocol. Which you seem to not be doing now.
So, in interface builder, set the tableview to be static and you can build the cells in interface builder and they will be displayed. Make sure you delete the boilerplatecode in table viewcontroller that is given to you to easily implement the protocol (if you don't delete it, the default code returns nil off the cells and so none will get displayed).
When you get it working, find a nice tableview tutorial. I suggest ray wenderlich or the cs193p course on itunesU.
Related
Hello guys i think almost everyone who is in ios development may come across the issue of reuse of the UITableCell by using following code line.
RZRestaurantListingCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
I have search lot about this but not getting any desire answer so please help me out in this case.
I have the same issue as most of iPhone developer having after reusing the cell.
I have the UIProgressView inside my cell and one button is there for downloading the video and i am showing the progress there in progress view how much is left.
So Now what i have problem is when i have more data and going out of the screen at that time i am press the download button on very first row of the UITableviewCell then i am scrolling down so the progress also shown in bottom random one cell so the UI changes in two cell rather then one.
You need to implement -prepareForReuse method in your custom cell class and set all cell properties to default value.
- (void)prepareForReuse
If a UITableViewCell object is reusable—that is, it has a reuse
identifier—this method is invoked just before the object is returned
from the UITableView method dequeueReusableCellWithIdentifier:. For
performance reasons, you should only reset attributes of the cell that
are not related to content, for example, alpha, editing, and selection
state. The table view's delegate in tableView:cellForRowAtIndexPath:
should always reset all content when reusing a cell. If the cell
object does not have an associated reuse identifier, this method is
not called. If you override this method, you must be sure to invoke
the superclass implementation.
Refer here for more, https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewCell_Class/#//apple_ref/occ/instm/UITableViewCell/prepareForReuse
You need to assign a progress value inside the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RZRestaurantListingCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// If the cell is reused, the `-prepareForReuse:` of `UITableViewCell` will be called.
//!! Assign current progress value to this cell, otherwise, the progressBar.value may look like a random value.
//!! Because the current cell is reused from a disappeared cell.
cell.progressBar.value = ... ;
return cell;
}
The design may be complex, because the progress may be updated continuously when the cell is on the screen.
Use prepareforreuse method to clear content of cell before using it... e.g.
-(void)prepareForReuse
{
[super prepareForReuse];
self.textLabel.text = #"";
self.detailTextLabel.text = #"";
self.imageView.image = nil;
}
I used a tutorial online to create a slide out side bar (similar to the facebook app).
It's based on using a table view as the side bar.
I cannot change the size (row height) of an individual cell as the table is set to dynamic (as specified by the tutorial. I change the row height in the IB and it makes no difference when running. It turns out I need a static table to use this.
When I change the table to static, it breaks my app with the following code causing the problem. I know a dynamic table is when you want to reuse cells and therefore dequeueReusableCell will cause a problem.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [self.menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
I don't have much experience with TableViews past this specific tutorial so just need a little bit of help amending the code so I can use a static table.
Thanks
If your table view isn't static, don't make it static to handle the row height. Instead, implement the table view delegate method tableView:heightForRowAtIndexPath: and return the appropriate height for each row.
Setting the height in the XIB / storyboard can have an effect but it depends on the overall configuration as to exactly what (if anything) it will do.
I need a grouped UITableView similar to the one for Twitter accounts in Settings app:
That is, a sort of form or menu where some of the sections have a beforehand known set of static cells, and some other sections have to be dynamic and allow inserting additional rows the same way the "Add Account" does here. I'm managing the UITableView in a .xib file. For the static cells, I have separated .xib files that I can load within the cellForRowAtIndexPath: method in the view controller.
How should I handle this kind of table? I don´t find any example code.
How the cellForRowAtIndexPath: method should look like? May I need to keep strong properties for the static cells? Would it be better to design each static cell directly within the same .xib file where the table view is, and to set outlets for them? (Though this does not allow to reuse my custom cells design...)
I need some guidelines for achieving this and correctly managing cells and memory. Thanks in advance
Dynamic prototype cells can behave like static ones if you just return the cell without adding any content in cellForRowAtIndexPath, so you can have both "static like" cells and dynamic ones (where the number of rows and the content are variable) by using dynamic prototypes.
In the example below, I started with a table view controller in IB (with a grouped table view), and changed the number of dynamic prototype cells to 3. I adjusted the size of the first cell to 80, and added a UIImageView and two labels. The middle cell is a Basic style cell, and the last one is another custom cell with a single centered label. I gave them each their own identifier. This is what it looks like in IB:
Then in code, I did this:
- (void)viewDidLoad {
[super viewDidLoad];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five"];
[self.tableView reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 1)
return self.theData.count;
return 1;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0)
return 80;
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if (indexPath.section == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"TitleCell" forIndexPath:indexPath];
}else if (indexPath.section == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:#"DataCell" forIndexPath:indexPath];
cell.textLabel.text = self.theData[indexPath.row];
}else if (indexPath.section == 2) {
cell = [tableView dequeueReusableCellWithIdentifier:#"ButtonCell" forIndexPath:indexPath];
}
return cell;
}
As you can see, for the "static like" cells, I just return the cell with the correct identifier, and I get exactly what I set up in IB. The result at runtime will look like your posted image with three sections.
Static is just a provision on top of dynamic layout. Basically static is a WYSIWYG.
If you are not resistant to experiment with values, I would recommend go dynamic. There are hundreds of examples available, such as this and this.
As you go further, you would see yourself diverging towards two options when customizing dynamic table views:
Subclass UITableViewCell (more effort , but good in the long run). Again, follow this.
Play with UITableViewCell properties inside cellForRowAtIndexPath: (less effort and quick result but may or may not be performance-friendly due to possible redrawing)
The possibilities are endless, such as here where cell background view is customized.
I am setting up my UITableView using storyboard editor. For creating my cells I am using the standard delegate method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell"];
if (cell == nil)
{
// Do cell setup
}
// etc
return cell;
}
Except when the cell is dequeued the very first time it's not nil, as it should be. So the code inside the if statement is never executed.
People get this error when their reuse identifiers are inconsistent, so I went ahead and verified that I am using the exact same reuse identifier in my storyboard views as I do in my code. Still facing the issue. I also have several tableviews within the project and each one has a unique reuse identifier. Still no dice. Anyone know anything else that could be wrong here?
That's not how UITableView works anymore. Reading your question, I think you might be confused about how it worked before as well. If not, sorry, the first part of this is just review. :)
Without storyboard cell prototypes
Here's how it used to work:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// If the tableview has an offscreen, unused cell of the right identifier
// it will return it.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell"];
if (cell == nil)
{
// Initial creation, nothing row specific.
}
// Per row setup here.
return cell;
}
Here when you create the cell using the reuse identifier, you do only the initial setup here. Nothing specific to this particular row/indexPath.
Where I've put the Per row setup comment you have a cell of the right identifier. It may be a fresh cell, or a recycled cell. You're responsible for all setup related to this particular row/indexPath.
Example: if you set the text in some rows (likely) you need to set or clear it in all rows, or text from rows you set will leak through to cells you don't.
With storyboard prototypes
With storyboards, though, the storyboard and table view handle the initial cell creation! This is brilliant stuff. You map out your cell prototypes directly in the tableview when using storyboards, and Cocoa Touch will do the initial creation for you.
Instead, you get this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell"];
// You'll always have a cell now!
// Per row setup here.
return cell;
}
You're responsible for all the same per row setup as before, but you shouldn't need to write code to build your initial empty cell, either inline or in its own subclass.
As Ian notes below, you can still use the old approach. Just make sure not to include a cell prototype in the storyboard for the identifier you specify. The view controller won't be able to build your cell from the cell prototype, dequeueReusableCellWithIdentifier will return nil, and you'll be exactly where you were before.
I have a UITableViewController with UITextfield inside the tableview cells. If I scroll the table view, the user entered data in the textfields disappears. I tried to add the textfield data to a NSMutableArray but it still didn't work. Any help please.
When cellForRowAtIndexPath: is called, the cell you return has to be completely filled in with whatever data you want to show. So, if the cell includes a UITextfield, you'll need to set it's text property to the right value for that row in your data.
When a table cell disappears off the top or bottom of the screen, the UITableViewCell itself becomes available for re-use. (As you scroll, cells disappear, and new cells appear, but the UITableView class is re-using the UITableViewCell objects.) In cellForRowAtIndexPath: when you get a cached cell to use, you have to be sure to setup everything you want it to show for the row in question, otherwise you might see some odd behavior in your table.
Does this help?
EDIT:
Here's an example of the typical pattern used in cellForRowAtIndexPath:. Notice the use of dequeueReusableCellWithIdentifier:. That method returns a previously allocated but not in use UITableViewCell, if there is one. Notice further that if no cached cell is returned, the code creates a new one, and sets it up (with stuff that is independent of anything that might be row specific). Following that, you'd setup the cell as you need it for the row in question.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SearchResultsCellIdentifier = #"SearchResultsCellIdentifer";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:SearchResultsCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:SearchResultsCellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Your row-specific setup of the cell here
// ...
return cell;
}
Check the docs for specifics about these methods. There are LOTS of examples from Apple and elsewhere about how to implement tableViews.