How to customize programmatically uitableviewcell subclass, which has a nib? - ios5

I am using custom UITableViewCell with a nib file with name "MyCellNib",for example.
I my tableviewcontroller i register in viewDidLoad this nib like this:
[_table registerNib:[UINib nibWithNibName:#"MyCellNib" bundle:nil]
forCellReuseIdentifier:#"cell"];
in my cellForRowAtIndexPath: it looks like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
cell = [_table dequeueReusableCellWithIdentifier:#"cell"];
cell.clipsToBounds = NO;
return cell;
}
As u see i dont use standart pattern like if(cell == nil) etc.(as we do it in iOS4) - regiserNib method can do it for us.
So, the problem: I need to write some code in the cell subclass.
in my custom uitableviewcell subclass the method
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
is not called (i used it before to customizw the cell), but i need it to add some stuff on contentView programmaticaly..
Is there any way to customize my custom cell when it is created?

Figured it out.
All this pre-stuff can be performed in -(void)awakeFromNib method

Related

Get selected UITableViewCell on touch down

I need to get the the currently selected UITableViewCell as its tapped. So upon my finger touching the screen/cell I want to run a method from which I can say something as simple as:
selectedCell = cell;
cell being the one I just tapped and selectedCell being a copy I store.
I am using a custom subclassed UITableViewCell which is why I think I'm having trouble.
Just implement setHighlighted:animated: method on your own custom tableview cell like this.
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
[super setHighlighted:highlighted animated:animated];
NSLog (#"setHighlighted:%# animated:%#", (highlighted?#"YES":#"NO"), (animated?#"YES":#"NO"));
}
TouchDown
- setSelected:animated: is called on the cell itself on touch down here, you can inform a cells delegate
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[self.delegate willSelectCell:self];
}
declare custom cells delegate as property of the cell
#property id<MyCellDelegate> delegate;
TouchUP
save the cell in the delegate
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
_selectedCell = [aTableView cellForRowAtIndexPath:indexPath];
}
just pay attention to the fact that Cell Views can be reused

Tableview inside Flipview using Utility template

I'm new to iOS dev, so I do apologise for asking potentially dumb question.
What I want to do is something very similar to the default Weather app; where the app has a info button, it flips to another view which has a table along with a Done button to go back to the app.
I'm using the 'Utility Application' template which does most of this for me :)
However, I am now struggling to add a tableview into the flipview. Am I on the right path? I'm using storyboard at the moment - beginning to realise this is most likely a limitation on the GUI (after all a GUI can only go so far). If so, is this possible programatically and how would I go about applying it on a default 'Utility Application' template.
I'm using Xcode 4.2.
Any help would be appreciated. Thanks in advance :)
First of all, you'll want to drag and drop a UITableView onto your flipsideViewController in interface builder. Make sure that you like its delegate and data source to the view controller.
Then change flipsideViewController.h to create an instance variable for the array that will store the text for the cells labels and for the controller to conform to the tables delegate and data source methods.
#interface FlipsideViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *myArrayOfItems;
}
In flipsideViewController.m alloc/init and populate your array in viewDidLoad
myArrayOfItems = [[NSArray alloc] initWithObjects:#"firstItem",#"secondItem",#"thirdItem",#"fourthItem", nil];
And finally, copy and paste the following and you should have a working table!
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [myArrayOfItems count];
}
- (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 = [myArrayOfItems objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected cell index:%i",indexPath.row);
}

How to control a customized UITableViewCell within a UITableView Implemented within a UIViewController?

In my app I wish to have a UIViewController that will hold a UITableView in it. In this UITableView I wish to have a customized UITableViewCell (i.e. I wish to define my own elements in this CELL - image, labels and buttons - as seen in the image below). And... I want to create them in the Storyboard.
Now, setting the elements in the Storyboard is easy.
I understand how to connect the UITableView and set it in the UIViewController (including the delegates in the .h file and using the basic table delegate methods).
What I'm not clear about, is how to connect and control the customized UITableViewCell and its outlets. Can I create the Outlets and Actions within the UIViewController .h and .m files? Do I need to create a separated UITableViewCell.h/.m files and call on them in the cellForRowAtIndexPath method?
Can anyone suggest what's the best approach for my needs?
UPDATE:
Here is the code I used in cellForRowAtIndexPath while using the separated MyCell.h/m file option. This code is written in the ViewController.m file, where the UITableView is implemented.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ContentCell";
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//MyCell is the Objective-C Class I created to manage the table cells attributes.
//#"ContentCell" is what I had entered in the Storyboard>>UITableViewCell as the Cell Identifier.
if (cell == nil) {
cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//Here is the place I'm not clear about - Am I supposed to init the cell in a different way? If so, how?
}
cell.contentNameLabel.text = [self.dataArray objectAtIndex: [indexPath row]];
// this is the test I had done to check if the new "MyCell" object is actually getting what I would expect it to get. well... the text gets updated in the relevant label, so i guess it gets it
return cell;
}
When running the app, using the debugger break point, I can see that the code always skips the "if (cell == nil)" and never enters the code where the new MyCell object supposes to be allocated and initiated. Any idea what may I be doing wrong?
Correct, create separate UITableViewCell.h/.m files to match your custom UITableViewCell class and call on them in your cellForRowAtIndexPath method.
In your storyboard, set the class of your custom UITableViewCell to your custom class (e.g. CustomTableCell).
Your custom UITableViewCell class would contain IBOutlets which you would wire up in your storyboard, here is an example:
CustomTableCell.h:
#import "CustomStuff.h" // A custom data class, for this example
#interface CustomTableCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *titleLabel;
- (void)configureForCustomStuff:(CustomStuff *)stuff;
#end
CustomTableCell.m:
#import "CustomTableCell.h"
#implementation CustomTableCell
#synthesize titleLabel;
#pragma mark - Configure the table view cell
- (void)configureForCustomStuff:(CustomStuff *)stuff
{
// Set your outlets here, e.g.
self.titleLabel.text = stuff.title;
}
#end
Then, in your cellForRowAtIndexPath method, configure your cell:
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:#"CustomCellID"];
// Your custom data here
CustomStuff *customStuff = <YOUR CUSTOM STUFF>
[cell configureForCustomStuff:customStuff];

Using UITableViewCell in a UITableView

I'm a little confused with something. I'm trying to create a custom cell and I want to use the interface builder way.
The normal way I create a table is to have the table as:
.h
#interface AssessList : UIViewController {
IBOutlet UITableView *tblAssessList;
}
#property(nonatomic, retain) UITableView *tblAssessList;
#end
.m
- (NSInteger)
numberOfSectionsInTableView:(UITableView *)tableView {
return groupArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return totalArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"I am the text....";
return cell;
}
Now i've created a new class for the cell and I think I understand how to put that in. But can I leave the .h as
#interface AssessList : UIViewController
or does the class/nib with the full table on it have to be a UITableViewController?
Tom
does the class/nib with the full table on it have to be a
UITableViewController?
No. A UITableViewController is just a convenience UIViewController subclass which has a UITableView and is already setup as its delegate/datasource (it is declared as conforming to the UITableViewDelegate and UITableViewDatasource protocols), it also has pre-filled method implementations for these protocols in the template implementation file which Xcode generates for you. You can just as well do all of this yourself, I often do.
You should however make an IBOutlet for your UITableViewCell so that you can load it from the nib file (see the Loading Custom Table-View Cells From Nib Files in the Table View Programming Guide).
If you want to do in the Interface Builder Way, then create an xib (view xib). Drag and drop a UITableViewCell object from the obj palette. Customize it as you wish. In the tableView:cellForRowAtIndexPath: method, do this:
UITableViewCell * aCell = [tableview dequeueReusableCellWithIdentifier:#"SomeIdentifier"];
if (aCell == nil)
{
NSArray *arr = [[NSBundle mainBundle] loadNibNamed:#"CustomCellNibName" owner:self options:nil];
for (NSObject *anObj in arr) {
if([anObj isKindOfClass:[UITableViewCell class]]) {
aCell = (UITableViewCell *)anObj;
}
}
}
The identifier for the tableviewcell can be set in the IB.
I guess it should be sub class of UItableViewCell
i.e.
#interface AssessList : UITableViewCell
When you want a custom tableview cell you will also need a subclass of UITableViewCell..
A tutorial can be found on this blog
Keep in mind that quite a few things can be done without creating a custom cell, this includes adding the switch to make your tableview look like the one from settings.app, to the way the iPod displays songs.
In the assessList Class you are using the custom cell created in otherviewController (UITableViewCell subclass) so there is no need to change this line
#interface AssessList : UIViewController
Note:- the otherviewController should be a subclass of UITableViewCell

UITableView placeholder for dequeued cells

There's this stupid little thing thats annoying me and i'd love to hear your opinion about it.
I'm using a UITableView with custom UITableViewCell's to display some news item from an RSS feed. this is working great ,
the only problem is - when is scroll down, i see the "old" cells, and only when my scroll stops, it loads the new content.
So my question is - can i somehow put a placeholder so it would at least show "loading" when scrolling or some other kind of indication?
Thanks in advance :)
Shai
When do you fill you cells with content, normally you do this in the UITableViewDataSource
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
This will get called every time a cell is needed before displaying it. If you set the data form that cell here is will be update before it gets displayed.
If you are grabbing something from the web, which could take some time, this is the place to set any content that you grab from the web to loading or placeholder images.
Then in the UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
Start the async fetching of data and update the cell when the data is received.
To avoid duplication of previous data in new cell, use an unique CellIdentifier.
NSString *CellIdentifier = [NSString stringWithFormat:#"%i", indexPath.row];
NewsCell *cell = (NewsCell *) [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil)
{
cell = [[ActivitiesCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier];
}
In NewsCell.m file, use following code and load the new cell by calling initWithStyle method, instead of using loadNibNamed.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code.
}
return self;
}