As everybody knows, there is easy to initialise UITableViewCell:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
But how to create my own table view style definition "UITableViewCellStyleCustom"?
As the other answers already pointed out, there are tons of tutorials as on how to create your own cell style.
However, remember the preferred way to create a table view cell is to reuse one in tableView:cellForRowAtIndexPath: like so:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myIdentifier" forIndexPath:indexPath];
EDIT
If you want to implement your own version of initWithStyle:reuseIdentifier:, you can obviously create your own enumeration of cell styles, e.g.:
typedef NS_ENUM(NSInteger, MyTableViewCellStyle){
MyTableViewCellStyleFile,
MyTableViewCellStyleFolder
};
Then you can define a custom init method like so:
-(instancetype)initWithMyStyle:(MyTableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;
Apart from that, UITableViewCellStyleDefault is part of the enumeration UITableViewCellStyle in UIKit. So it is basically just an integer value and passing a different value than the defined will not work in default init methods.
There are a couple of solutions for this:
You prototype your own custom cell on a storyboard. This is a quick way of creating a custom cell without too much of a hassle. If I am not mistaken this is not available in NIBs.
Create your Cell in a NIB.
On both approaches, you will have to then subclass a UITableViewCell and add the behaviour you want to it. You will also need to specify on the Storyboard or Nib, that you want that cell to have the type of the subclass you just created. There a tons of tutorials on the web on how to do it.
First, you need to subclass UITableViewCell to get a custom cell.
When initializing in code (why?), just use UITableViewCellStyleDefault as the style parameter in the designated initializer. I recommend initializing the cell via storyboard or Interface Builder.
Related
I have the only cell template for items at two different UITableViewControllers/TableViews.
What I need is to define it once and then reuse at other UITableView via
UITableView.DequeueReusableCell(CellId);
The issue is that is when I call this method on UITableView which doesn't contain cell prototype I'm getting NULL.
How to reuse my prototyped cell across multiple table controllers?
I want to define cell template in storyboard, NOT xib.
It turned out that the only way to reuse a cell it to design it with xib and register at tableview that xib with cellid.
Just copy-paste your prototype cell in every table view controller where you need it.
And if I understand your question, in a standard and proper way, it's not possible to dequeue a cell from another table view, Apple implementation handles this mechanism itself.
Using xib for a reusable cell is beneficial while cell design is fixed in the whole app. But when there are conditional requirements or slight changes in design or functionality and remaining design and functionality is same for tableview cell, in this case if you still want to reuse the code then you can subclass tableview cell class.
Why should I set a Custom-class for a Cell within the UIBuilder? All examples I can find are setting the Identifier and use this on in ...cellForRowAtIndexPath:...?
Is this useless here?
Edit:
Sorry, I think, this was not asked clearly - so I'll try again:
Normally (all found examples) the Cell-Identifier (in the attributes inspector) is set an this ID is used in the ...cellForRowAtIndexPath:...-method to identify, which Class should be used.
Beside the Cell-Identifier (attributes inpector), there is the the possibility to set the custom class (identity inspector). When will I use this setting in the context of table-cells?
If you use Custom Cells in the Interface Builder, you can easily manipulate the appearance of your custom cell, and make it have custom properties and behave in specific ways which is very effective.
Custom Class is used whenever you make your own class for a UITableViewCell.
#import "UITableViewCell.h"
#interface MyCell : UITableViewCell
#property NSString *myCustomProperty;
#end
Then in the code, you can access the custom properties of your cell by doing something like:
MyCell *cell = (MyCell*)[tableView objectAtIndexPath:indexPath];
[cell setMyCustomProperty:#"Custom Cells Yey!"];
Also, may I also note that the identifiers are primarily used to manage memory effectively in UITableViews. The table views use trickery in their implementation to cache the cells rather than create new cells every time you scroll a little bit otherwise that would be overkill so you can use identifiers to cache rows in the tableview automagically.
I am creating a Custom UITableViewCell with a UITextfield in it, I would like to know how to access the the custom UItableViewCell from the UITextField delegate didend?
I am trying this
- (void)textFieldDidEndEditing:(UITextField *)textField {
CustomFinishingCell *updateCell = (CustomFinishingCell *)textField.superview;
but that's not returning a UITableViewCell, I think it's returning the UItableScrollView or something like that.
The textField's superview will actually be the cell's contentView. You could probably get the cell by doing:
CustomFinishingCell *updateCell = (CustomFinishingCell *)textField.superview.superview;
That's a little clunky though.
I also wouldn't recommend using tags as that's even more clunky.
What I would do, is create a subclass of UITextField with a property for your CustomFinishingCell and set that when creating the cell (where you add the UITextField). That will ensure everything keeps working, even if the user resorts the cells, adds/removes cells etc, and will work well with cell reuse.
Update:
In a lot of cases, it will be better to actually use #TimReddy's answer and set the delegate of the UITextField to the CustomFinishingCell and move the - (void)textFieldDidEndEditing:(UITextField *)textField etc code to that subclass. That will save you having to create another subclass for UITextField.
You need to have your custom UITableViewCell be that UITextView's delegate. That way you know for certain when the delegate fires it is that UITableViewCell's text view.
You may need to so some cleanup work before the UITableViewCell gets recycled tho.
You could give each cell view a tag, then call UIView's viewWithTag to get the view with the specified tag.
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
This is how I do it:
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[textField convertPoint:textField.frame.origin toView:self.tableView]];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
I prefer this approach because it doesn't rely on tags or maintaining a reference to the container view from the UITextField, or traversing the view hierarchy. All those approaches are brittle for one reason or another.
Tags approach: You need to set the tag in tableView:cellForRowAtIndexPath: and if you have multiple sections, you need to encode the section.
Adding a property to UITextField: This either requires a UITextField category and associated objects, or subclassing UITextField. Both work, but are overkill.
Traversing the view hierarchy is brittle because it depends on implementation details that could change at any time.
I have a static UITableView built from a Storyboard that works well. I want to fill the first category programmatically, though, from a user-defined file
Simply put, I want to go through all the strings in an array and add them as cells for the rows of the first category. For the second category, I have a series of mildly complex cells (containing a number of labels, textfields, buttons and other controls), defined in the storyboard, that I don't feel like recreating in code.
As far as I understand, the default behaviour for a UITableView built from a storyboard is to use the nib file as an implicit datasource. If I use a custom class as datasource, my second section doesn't work. I have thought of two possible ways to fix this:
Fill my first category from the datasource and delegate the rest to the nib file. Is this possible? Is there some method to programmatically ask the nib to fill my UITableView?
Export my storyboard-built cells into code and paste this code into my datasource. This method has the disadvantage of making my second category harder to modify.
Is one of those two options feasible? Is there another option?
I would use dynamic prototype cells. Then, I would set up the ViewController as the delegate and the dataSource. I would then create a custom subclass of UITableViewCell and connect the elements of the second section to IBOutlets in the custom UITableViewCell.
If the first section wasn't something that could be done with one of the generic cell types, I would also create a custom subclass of UITableViewCell for that section as well.
I would then use the cellForRowAtIndexPath: method to set up the cells with the information that I want in them. So if my first section used FirstSectionCell and my second section used SecondSectionCell as custom subclasses of UITableViewCell my cellForRowAtIndexPath: would look like this:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
FirstSectionCell *firstCell = [tableView dequeueReusableCellWithIdentifier:#"First Cell Prototype"];
//Set up the first cell.
return firstCell;
}
else if(indexPath.section ==1)
{
SecondSectionCell *secondCell = [tableView dequeueReusableCellWithIdentifier:#"Second Cell Ptototype"];
//Set up second cell.
secondCell.someLabel.text = #"whatever";
//etc.
return secondCell;
}
else
{
//if you have another section handle it here.
}
}
There are two kinds of table views when you use Storyboards:
Static
Dynamic
You're currently using the former. You define everything in the Storyboard and have very little code.
But you need to change to the latter.
You can still keep your UITableViewCells in the Storyboard; there's no need to do that in code (though you can if it makes things easier). You can refer to the template cells using the "reuse identifer."
Otherwise you've pretty much got it. You'll need to write code to implement the data source and (possibly) more methods of the table view delegate.
It's kind of fiddly switching from static to dynamic. I keep meaning to raise a Radar because I'm sure Xcode could be making it easier to do...
Again I'm moving from Xcode 3 to 4 and finding that some things are different. I'm writing a splitview iPad app and working from all the code that was generated for me. In the master view I want to customize the UITableViewCell to use the UITableViewCellStyleSubtitle style. In the past that was simple and I knew it was done within tableView:cellForRowAtIndexPath:.
In the new template code there is no [[UITableViewCell alloc] init....] there is only
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
so I can't modify the style here. I looked in the storyboard and found the cell but cannot seem to change the property there either.
In short, I can't find where the UITableViewCells are alloc/init'ed so that I can make my change. Where is this done in Xcode 4?
If you're using the storyboard-based template, the cell is created by the storyboard, so you need to configure it in the storyboard in IB. If you haven't found that, it's here:
Select the cell, and it'll be in the attributes inspector. While you're there you might want to set a reuse identifier you can use in tableView:cellForRowAtIndexPath:.
(You can also use IB to change the font or other properties of the cell's textLabel and detailTextLabel and set accessory styles like you would have before in tableView:cellForRowAtIndexPath:.)
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
This is still done in cellForRowAtIndexPath