How to set a tableView Cell Identifier in a UIViewController? - ios

Who do to set a tableView Cell Identifier in a UIViewController ?
Using UITableViewController I always do it through the interface (see screenshot below)
Now I dont see that option if I use UIViewController
here's my code
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
NSString *messageAtIndexPath = [messageArray objectAtIndex :[indexPath row]];
[[cell textLabel] setText:messageAtIndexPath];
return cell;
}
please advice
Unless I add a prototype cell which messes my interface.

A couple things here:
1) A UITableViewController inherits from UIViewController (which I think is what you are actually talking about, instead of "UIControllerView"). UITableViewControllers have the ability to do prototype cells and set these identifiers...
2) ... which are case sensitive. In your screenshot, you call it "cell" while in your code you call it "Cell".
They need to be spelled exactly the same and in the same upper/lower case way.
It's not super clear what you are trying to do here, but I sense that you want to create a custom cell in your XIB or storyboard and then reference it in your "cellForRowAtIndexPath:" method. Here is a tutorial that talks about prototype cells and identifiers and using them in storyboards, and I hope this helps you out.

Related

Custom prototype cell in UIStoryboard is created but doesn't show up in UITableView

I have a project where I need to use a custom UITableViewCell. I'm designing the cell as a prototype in storyboard and it looks fine there. I assign the prototype to my custom UITableViewCell subclass, give it the same reuse identifier I'm using in my UITableView and link the UILabel on the prototype cell to an IBOutlet in my UITableViewCell subclass.
When I call it from the UITableView the cell is created and if I add labels and buttons in the code of that class (create them with a CGRect and all) they all work but the labels I've added in the storyboard never show up.
I don't understand how my subclass can be called and created successfully but its layout and subviews from the storyboard don't seem to exist as far as my app is concerned. What am I doing wrong?
Here's my cellForRowAtIndexPath code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
return cell;
}
I've run into this issue before, and in my case, the problem was that the auto-generated code for the view controller included a call to:
[UITableView registerClass:forCellReuseIdentifier:]
I would suggest checking for and removing any calls to the above, or to
[UITableView registerNib:forCellReuseIdentifier:]
and trying your original code again.
acreichman, add casting in cellForRow and put an NSLog in you cell's awakeFromNib to see if you get there. Let me know...
Your cellForIndexViewPath should look like this, to create a simple custom cell with label,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
Make sure that you have made all connections well, set datasource and delegate to table and then set the “Identifier” of the custom cell to "MyTableViewCell" in “Attributes Inspector” like this,
For storyboard:
Add "MyTableViewCell" instead of "SimpleTableCell" as shown in above screenshot.

List Songs in UITableViewController on iPhone? Works in Storyboard, NOT without it

I am NOT using Storyboards. I have a UITableViewController and I would like to display a list of songs from user's library.
This is my code so far:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
NSArray *songs = [songsQuery items];
return [songs count];
}
But for this block, I do not know what to do. I found a tutorial for storyboards, but it is not valid here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
NSArray *songs = [songsQuery items];
MPMediaItem *rowItem = [songs objectAtIndex:indexPath.row];
cell.textLabel.text = [rowItem valueForProperty:MPMediaItemPropertyTitle];
cell.detailTextLabel.text = [rowItem valueForProperty:MPMediaItemPropertyArtist];
return cell;
}
This only works in Storyboard because I can click the cell in the storyboard and rename its identifier to 'Cell'. In the .xib/nib file in my project, all I see is a view filled with country's names. I cannot click a single cell, I can only edit the whole table.
My question is, what code must I put in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath in order to display this list?
Thanks!
The basic problem you're encountering is that, when used in conjunction with a properly configured storyboard, dequeueReusableCell... will create a cell of the appropriate type if none is available to dequeue.
If you are using a standard UITableViewCell, you can use the following block to dequeue and/or create an appropriate cell:
static NSString* reuseIdentifier = #"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
}
If, on the other hand, you're loading your cells from a nib file, you can just add:
[self.tableView registerNib:[UINib nibWithNibName:nibName bundle:[NSBundle mainBundle]] reuseIdentifier:reuseIdentifier];
to your viewDidLoad.
Alternatively you can use registerClass:forCellReuseIdentifier: if you have a custom cell class that sets up it's own subviews.
First off, check if the cell being dequeued is nil or not.
The next thing I can see a problem with is the fact that you aren't really loading anything in cellForRowAtIndexPath:. Basically what this method does is dequeue some cell which has been marked for reuse in an attempt to save memory, and if you haven't set the proper Restoration Identifier in the Interface Builder, then there is no way to know which Nib you want initialized to use here.
What used to happen (or at least my understanding of it) is that in cellForRowAtIndexPath: you would have to check if the cell returned from dequeueReusableCellWithIdentifier: was nil, and if so, you'd have to create the cell from scratch using something like this:
SomeCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"SomeCellNib" owner:self options:nil] objectAtIndex:0];
}
and this would ensure that if no cell was dequeued that you would load up a fresh one from scratch, although I believe that Apple actually changed how dequeueReusableCellWithIdentifier: works, and as long as you've registered the Identifier, it will create a new cell for you.
For this reason I'm not sure what the problem is if you've set the Identifier properly, and all I can suggest is to try and manually load the cell.
EDIT: I forgot to mention where Restoration Identifiers can be set. The Restoration Identifer field is in the Identity tab, or the third tab in the Interface Builder:
To create a prototype cell inside a .nib, drag a UITableCellView out from the right sidebar. From there you can create your cell prototype, as well as set the cell reuse identifier.

Table cells doesn't connect to outlet in iOS storyboard

I followed Connect outlet of a Cell Prototype in a storyboard
So my outlets are connected. I have this method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HomeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"] ;
}
// Configure the cell.
Group * group = [self.groups objectAtIndex: [indexPath section]];
Friend * friend = [[group friends ]objectAtIndex: [indexPath row]];
NSLog(#"%#", friend.name);
[[cell nameLabel] setText:friend.name];
[[cell statusLabel] setText:friend.status];
[[cell picImageView] setImage:[UIImage imageNamed:#"similey.jpg"]];
return cell;
}
It compiles fine but the cells show up blank with nothing in it. Any suggestions?
Did you set the identifier of the cell in the storyboard to "Cell" to match your dequeueReusableCellWithIdentifier call?
Interface Builder creates objects, and then allows you to replicate them. It doesn't change the definition of a class. So if you design an instance of a class in Interface Builder, you're only designing that single instance. Loading Storyboards and NIBs are mechanisms you can use to replicate that instance.
Designing an instance of a class in IB, and then later going and doing a direct alloc+init of that class will result in an instance completely independent of the one in Interface Builder.
This following line of code indicates to me that you're expecting the instance in the storyboard to have an influence on what happens when you alloc+init your class directly:
[[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"]
If you're ever hitting that line, that's probably your problem. That line shouldn't be there if you created the cell in the storyboard. For cells created in the storyboard, -dequeueReusableCellWithIdentifier: will always return an instance of the cell provided that you matched up the identifiers.
Since HomeCell is a custom UITableViewCell it won't be in a reuse queue, so your table view will need to know about it through the registerClass method, like this:
- (void)viewWillAppear:(BOOL)animated
{
...
[self.tableView registerClass:[HomeCell class] forCellReuseIdentifier:#"Cell"];
}

Using alloc and init when using a UITableViewCell from Storyboard

I'm doing a simples app using Storyboard that a have a View with a UITableView with a UITableViewCell that do the navigation to another UIView.
So a have to code to populate the cell on the table view.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"SampleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
NSLog(#"cai no init da cell");
}
GPItem *item = [self.items objectAtIndex:indexPath.row];
cell.textLabel.text = #"Post";
cell.detailTextLabel.text = item.imageURL;
return cell;
}
I realised that the code if (cell == nil) { ... never executes so I really need to do that on uses the cell from Storyboard?
Thanks.
You are correct; that code is guaranteed to return a non-nil cell if you are using a storyboard. Also, in iOS 6, the new call dequeueReusableCellWithIdentifier:forIndexPath: never returns nil. See the discussion in my book:
http://www.apeth.com/iOSBook/ch21.html#_registering_a_cell_class
If you've declared your UITableViewCell in table view's prototype cells it's already allocated and just needs to be dequeued. If you're using a custom UITableViewCell subclass, then you must check if it's nil and allocate new entities when necessary.
Nope you don't need that code when using a cell made in your storyboard.
It is probably best to remove this code so that you crash nice and early if the identifier you gave to the cell in interface builder and the identifier you use in code ever drift. This snippet will mask this error and just provide a cell that you most likely was not intending to have.

Error while adding UICollectionView inside UITableViewCell

So I am trying to display horizontally scrollable collection view inside tableviewcell. the code i am using is
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UICollectionViewController *cv = [self.storyboard instantiateViewControllerWithIdentifier:#"collectionViewID"];
cv.view.frame = cell.contentView.bounds;
[self addChildViewController:cv];
[cell.contentView addSubview:cv.view];
[cv didMoveToParentViewController:self];
return cell;
}
I am getting error: Object can not be nil. I'd appreciate if someone can help me out understanding the error.
I have done this in my app.
I found it much easier to subclass UITableViewCell. The I could put all the UICollectionView setup and the UICollectionView datasource and delegate inside the code for the cell.
I then provided one public property of type NSArray which I pass into the cell. The cell then uses this array as the datasource for the UICollectionView that it owns itself.
Made it a lot easier to manage.
check your UICollectionViewControlle's attribute inspector for identifier value {collectionViewID}
EDIT
[self addChildViewController:cv]; --> I think you want to add cv to the cell, isn't you?

Resources