iOS 6 Collection View Controller multiple dynamic cells - iphone

I am only a week into Xcode, trying to learn something, so I can contribute to a project..
So far I've been looking into tutorials and made something :) But I'm far from over. I hope someone will understand what I'll be asking..
I'm making an app that will take data from a server, the data will include thumbnail images, images and text. Right now I have a collection view controller, with a cell that has 3 buttons (I find them easier to place around in the collection view cell), the button's background is a specific image (hard coded for now), and it takes you to a view controller, where all the content for that item are shown, nothing special :)
But the layout (design) is hard for me to achieve. Basically (from my understanding) I need to have 4 collection view cells, with different positioned buttons. Now I have one collection view controller, with one collection view , containing one cell.
#import "CollectionViewController.h"
#import "CollectionViewCell.h"
#import "ImageDetailsViewController.h"
#import "StoryItem.h"
#interface CollectionViewController ()
{
NSArray *arrBigLeft;
NSArray *arrSmallTopR;
NSArray *arrSmallBotR;
}
#end
#implementation CollectionViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
arrBigLeft = [[NSArray alloc]initWithObjects:#"imageicon0#2x.jpg", #"imageicon1#2x.jpg", #"imageicon2#2x.jpg", #"imageicon3#2x.jpg", nil];
arrSmallTopR = [[NSArray alloc]initWithObjects:#"imageicon4#2x.jpg", #"imageicon5#2x.jpg", #"imageicon6#2x.jpg", #"imageicon7#2x.jpg", nil];
arrSmallBotR = [[NSArray alloc]initWithObjects:#"imageicon8#2x.jpg", #"imageicon9#2x.jpg", #"imageicon0#2x.jpg", #"imageicon1#2x.jpg", nil];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"photoDetail1"]){
CollectionViewCell *cell = (CollectionViewCell *)sender;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
ImageDetailsViewController *idvc = (ImageDetailsViewController *)[segue destinationViewController];
idvc.img = [UIImage imageNamed:[arrBigLeft objectAtIndex:indexPath.item]];
}
if([segue.identifier isEqualToString:#"photoDetail2"]){
CollectionViewCell *cell = (CollectionViewCell *)sender;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
ImageDetailsViewController *idvc = (ImageDetailsViewController *)[segue destinationViewController];
idvc.img = [UIImage imageNamed:[arrSmallTopR objectAtIndex:indexPath.item]];
}
if([segue.identifier isEqualToString:#"photoDetail3"]){
CollectionViewCell *cell = (CollectionViewCell *)sender;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
ImageDetailsViewController *idvc = (ImageDetailsViewController *)[segue destinationViewController];
idvc.img = [UIImage imageNamed:[arrSmallBotR objectAtIndex:indexPath.item]];
}
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [arrBigLeft count];
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier=#"Cell";
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
[[cell button1]setBackgroundImage:[UIImage imageNamed:[arrBigLeft objectAtIndex:indexPath.item]] forState:UIControlStateNormal];
[[cell button2]setBackgroundImage:[UIImage imageNamed:[arrSmallTopR objectAtIndex:indexPath.item]] forState:UIControlStateNormal];
[[cell button3]setBackgroundImage:[UIImage imageNamed:[arrSmallBotR objectAtIndex:indexPath.item]] forState:UIControlStateNormal];
return cell;
}
-(IBAction)returned:(UIStoryboardSegue *)segue {
}
#end
This doesn't work as I want it to yet, but at least I'm getting dynamically created cells. I'd like to be able to return multiple cells, with different arrays of items (images), and they all should load at the same time
here you can see only two cells, but the second one I added just to visualize what I'm trying to explain (4 different cells)
The first cell (because of the number of images) repeats 4 times when I ran the app, if I was about to add the same images to the second cell, I would like to see them as in the screen shoot, and to continue to repeat in that order equal to the number of images (length of array)
If you need more code, let me know.. thanks!

I suggest following this to get a basic understanding of whats required.
http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12
Than you can advance to more complex designs. Looks like your jumping into the deep end. But this tutorial is really good.

Related

CellForRowAtIndexPath is not invoked

I'm writing an app hat has many views and I used sliding views library (ECSlidingViews). The problem is when I fill an array with objects and fill the table with the objects in tableView:cellForRowIndexPath: method, it does present the data in the table, but when I go to other view and come back the data disappears because tableView:cellForRowIndexPath: is not called. Here is the code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"begin of cellForRowAtIndexPath");
SchedualeCell *cell = (SchedualeCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
Course *temp = [array objectAtIndex:indexPath.row];
cell.nameLb.text = temp.name;
cell.hourLb.text = [NSString stringWithFormat:#"%d",temp.hour];
cell.startTimeLb.text = temp.startTime;
cell.endTimeLb.text = temp.endTime;
NSLog(#"End of cellForRowAtIndexPath");
return cell;
}
tableView:numberOfRowsInSection: and numberOfSectionsInTableView: is invoked when I come back to the view that has the table view.
P.S.: The view is UIViewController that has table view inside of it, and I searched all StackOverflow before posting my problem.
EDIT : this is where I set the delegate and datasource
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Did Appear");
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor= [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]])
{
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
if (array == nil)
{
array = [[NSMutableArray alloc]init];
}
table.delegate = self;
table.dataSource = self;
[table reloadData];
}
and I did included The delegate and datasource in the header
#interface MainViewController : UIViewController<UITableViewDataSource , UITableViewDelegate,addDelegate>
First of all , it's not numberOfRowsAtSection and numberOfTableView. It's numberOfSectionsInTableView and numberOfRowsInSection.
Things you can do :
1) NSLog your numberOfRowsInSection. Note that , If it's "0" then your cellForRowAtIndexPath is never going to be called.
2) If you are using your UITableView inside some UIView then you should add :
[self.view addSubview:table];
3) Don't Forget to include :
#interface yourViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
Once check that you reframed the tableview in ViewWillAppear.
Some times if we set out of frame, CellForRowAtIndexPath will not call.

iOS: dynamically adding data from UITableView to NSArray

I have a UITableView in which I have a custom prototype cell, defined in another class (CustomCell), with a UITextField in it. Every time I press a button, it calls a method called addItem, which creates a new cell. I want the texts in the UITextFields to go to an array. To try to explain it better, if I add 3 cells to the UITableView and input 3 texts in the corresponding UITextFields, I want the text in 1st cell to go to the array in index 0, the text in the 2nd to go to index 1 and the text in 3rd cell to go to index 2. My biggest problem is that I want to be able to go back to UITextField in cell 1 and update it, and have it dynamically update the NSArray object corresponding to it, that is, the one at index 0. I have no idea how to approach it. Can anybody help???
Thank you very much!!
my code (obs: itemTable is the UITableView):
MainViewController.m
#implementation addViewController{
NSInteger n;
NSString *aid;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewWillAppear:(BOOL)animated{
n=1;
aid=#"";
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return n;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier= #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.itemNumber.text=[NSString stringWithFormat:#"Item %d",indexPath.row];
return cell;
}
- (IBAction)addItem:(UIButton *)sender {
++n;
[_itemTable reloadData];
}
- (IBAction)removeItem:(UIButton *)sender {
if (n>=0)--n;
[_itemTable reloadData];
}
CustomCell.m:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {_itemValue = [[UITextField alloc]init];
_item = [[UILabel alloc]init];
[self.contentView addSubview:_itemValue];
[self.contentView addSubview:_item];
}
return self;
}
CustomCell.h
#interface CustomCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *itemNumber;
#property (strong, nonatomic) IBOutlet UITextField *itemValue;
#end
First, when you create each text field, you make yourself that text field's delegate, so you will get messages whenever something happens in the text field.
Okay, so now when the user types in a text field, you will get messages, and you can modify your model (the array, which you should keep as an NSMutableArray I suppose). But to do that, you need to figure out which the heck cell contains the text field that this message is coming from! You will do that something like this:
- (void)textFieldDidEndEditing:(UITextField *)tf {
// some cell's text field has finished editing; which cell?
UIView* v = tf;
do {
v = v.superview;
} while (![v isKindOfClass: [UITableViewCell class]]);
CustomCell* cell = (CustomCell*)v;
// so which row is it?
NSIndexPath* ip = [self.tableView indexPathForCell:cell];
// aha! so now ip.row is the row, and you can update your data model
// ... left as an exercise for the reader ...
}
I do exactly this sort of thing in my book, in http://www.apeth.com/iOSBook/ch21.html#_editable_content_in_table_items (that's where the above code comes from), so take a look and see what ideas it gives you.
When the user is done entering text you could do something like the following which maps the index paths of the rows in your tableview to the indices in an array.
- (NSMutableArray *)updateText {
NSUInteger cellsCount = [self.tableView numberOfRowsInSection:0];
NSMutableArray *cellTextArray = [[NSMutableArray alloc] initWithCapacity:cellsCount];
for(NSInteger i = 0; i < cellsCount; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
CustomCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
NSString *item = cell.itemNumber.text;
[cellTextArray insertObject:item atIndex:i];
}
return cellTextArray;
}
Assuming your cell has the UITextFieldDelegate set, when the user is done entering text you can do something like this:
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self.delegate didFinishEditing];
}
Where self.delegate is the UITableViewController, which in turn call updateText when necessary.
Things to be careful of - the for loop in updateText needs to loop over the tableview and dequeue cells for each index path. Simply using the tableview's visible cells would most likely leaving you missing text from cells that were off screen and got reused.
Hope this helps and good luck!
There are obviously a few aspects of this problem. First of all, you want to be able to recover references to the UILabel's, so that you can figure out which row a specific UILabel is in. I'd recommend doing this using the tag property, like this:
_item = [[UILabel alloc] init];
_item.tag = 100; // or any value
[self.contentView addSubview:_item];
You also need to set an action that gets called whenever the text in the label gets changed. You can do that like this:
[_item addTarget:someObject
action:#selector(labelChanged:)
forControlEvents:UIControlEventEditingChanged];
Whatever class someObject is, it needs to have a method with this signature:
- (void)labelChanged:(id)sender;
Inside that method you can check that sender is in fact a UILabel, and then you can access the new text with sender.text.
In order to figure out what point in the array to put the text in, you can declare a loop over the number of rows in your table:
for (int i = 0; i < [mainViewControllerInstance tableView:theTableInQuestion numberOfRowsInSection:0]; ++i) {
if(sender == [[mainViewControllerInstance tableView:theTableInQuestion
cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] viewWithTag:100]) {
// Put `sender.text` in the appropriate spot in your array
}
}
A few additional notes: I'd use an NSMutableArray to keep track of your strings, since you'll be updating them, but I'm not entirely sure what best practices are here. You'll also want to make sure you initialize your array (whether you make it an NSArray or an NSMutableArray) to have the proper number of rows, and make sure that you add rows to it when the + button is pressed, or you'll risk getting an exception when you try to change an entry for a row that doesn't yet exist.
You might also want to have a look at the free Sensible TableView framework. The framework performs almost all what you need automatically. Should probably save you a lot of manual work. Good luck!

iPhone didSelectRowAtIndexPath not invoke for cells number 10, 20,30

here is the thing. I have a tableview with a variable number of rows. When you tap one of them, a detail view is shown.
Everything is ok if you tapped rows from 0 to 9, 11 to 19, 21 to 29 etc... But it doesn't work for rows number 10, 20, 30 etc... Even a long tap is detected on this rows, so an alert is shown, in order to delete the row if necessary (and I can remove it without problems), but didselectrowatindexpath is Never called.
I think is something involved that the tableview only keeps 10 rows at the same time. But in cellForRowAtIndex everything loads ok, for all rows. I keep all the data in some NSMutableArray, to access the data I need with [indexPath row].
I have already spend some time looking for similar post, but don't find anything like this.
any help will be appreciate. Thanks!
Some code:
// in .h
#import <UIKit/UIKit.h>
#import "PullRefreshTableViewController.h"
#import "DetalleMailViewController.h"
#interface MensajesTableViewController : PullRefreshTableViewController <DetalleMailViewControllerDelegate>
#property (nonatomic, strong) NSMutableArray *mailAuthors;
#property (nonatomic) int row_tabla_delete;
- (IBAction)presentMenu:(id)sender;
#end
//in .m make the synthesize of mailAuthors and some relevant code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.allowsSelection = YES;
//This gesture works fine
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(presentMenu:)];
lpgr.minimumPressDuration = 0.5; //seconds
lpgr.numberOfTouchesRequired =1;
lpgr.delegate = self;
[self.tableView addGestureRecognizer:lpgr];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *idCell = #"mailTableCell";
MailCell *celda = [tableView dequeueReusableCellWithIdentifier:idCell];
if(celda == nil){
celda = [[MailCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:idCell];
}
celda.mailAuthor.text = [self.mailAuthors objectAtIndex:[indexPath row]];
return celda;
}
-(void) viewWillAppear:(BOOL)animated{
[[self tableView] reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//I really use a segue here, but for the sake of simplicity, I just put a trace, never called for rows 10, 20, 30... The segue works fine the rest of the time...
NSLog(#"tapped %d", [indexPath row]);
}
- (IBAction)presentMenu:(id)sender {
if ([sender state] == UIGestureRecognizerStateBegan){
CGPoint p = [sender locationInView:self.tableView];
NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath != nil){
self.row_tabla_delete = [indexPath row];
}
//some code to delete the row
}
}
In MailCell.hI have theUILabelfor mailAuthor as a property, and linked in the storyboard with the UILabel inside theUITableViewCell. In the storyboard, I have aTableViewController linked to my own class "MensajeTableViewController", theUITableViewCellto my "MailCell`".
If there is some need to add some other relevant code, or something else, please Help me.

TableView is not loading data?

In my Map application I have segment controller on main screen and using that I have Map View & tableview(both are UIView). I have tried everything but my data is not loading in my tableview. Here is my tableview code. Here marker is attribute in my xml file which contain Showroom name and Iam able to parse this.
.h file
#interface HViewController : UIViewController<UITableViewDataSource, UITableViewDelegate> {
UITableView *_tableView;
}
#property (nonatomic, retain) IBOutlet UITableView *_tableView;
#end
.m file
Edited = with ViewWillAppear,viewDieLoad, segement action method
#synthesize tableView;
- (void)viewDidLoad {
appDelegate = (HAppDelegate *)[[UIApplication sharedApplication] delegate];
[segmentedControl addTarget:self action:#selector(segmentAction:)
forControlEvents:UIControlEventValueChanged];
}
- (void)viewWillAppear:(BOOL)animated
{
self._tableView.rowHeight = 80.0;
[_tableView reloadData];
}
-(void)segmentAction:(id)sender;{
UISegmentedControl* segCtl = sender ;
if( [segCtl selectedSegmentIndex] == 0 )
{
NSLog(#"segmentAction mapView");
mapView.hidden = NO;
_tableView.hidden = YES;
//[ self.view addSubview:mapView] ; // adding view to segmentindex 0
}
if( [segCtl selectedSegmentIndex] == 1 )
{
NSLog(#"segmentAction _tableview");
_tableView.hidden = NO;
mapView.hidden = YES;
//[ self.view addSubview:_tableview] ;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"appDelegate.markers _tableview");
return [appDelegate.markers count];
}
//method to print row(showroom count on Header)
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection: (NSInteger)section {
if(section == 0)
return [NSString stringWithFormat:NSLocalizedString(#"ShowRooms[%d]", #"Showroom format"), [appDelegate.markers count]];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSUInteger const kShowroomNameLabelTag = 2;
UILabel *ShowroomNameLabel = nil;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
ShowroomNameLabel = [[[UILabel alloc] initWithFrame:CGRectMake(50, 1, 300, 20)] autorelease];
ShowroomNameLabel.tag = kShowroomNameLabelTag;
ShowroomNameLabel.font = [UIFont boldSystemFontOfSize:18];
[cell.contentView addSubview:ShowroomNameLabel];
NSLog(#"UITableViewCell.markers _tableview");
}
else
{
ShowroomNameLabel = (UILabel *)[cell.contentView viewWithTag:kShowroomNameLabelTag];
}
marker *aMarker = [appDelegate.markers objectAtIndex:indexPath.row];
//ShowroomNameLabel.text = aMarker.name;
ShowroomNameLabel.text= [NSString stringWithFormat:#"ShowroomName= %#", aMarker.name];
return cell;
}
In my tableview Header it shows data count correctly but not showing data.
I have connected delegate,datasource,_tableview to fileOwner of the HViewController in which I have put above code. Plz suggest something where I am wrong. I am parsing XML file and getting data in console alos I can show it on Map. But I am not able to load data in my tableview.
Try moving [_tableView reloadData] to viewWillAppear.
UITableViewController reloads the table view's data in viewWillAppear, not viewDidLoad. I can't tell you the exact reason for which this would make a difference, though I can think of several. Anyway, it's worth a try.
EDIT:
RESPONSE TO COMMENTS
If titleForHeaderInSection: is being called, then there is a data source connected to a table view. So, the problem is not a lack of a data source connection.
I am guessing you have 2 table views in your .xib file: a large one & a short one below it. The large table view is not connected to the data source, so it just displays blank lines. The short table view is connected to the data source. But, it is just tall enough for a header and has no space left to display any cells. Thus, titleForHeaderInSection: is called, but cellForRowAtIndexPath: is not because there is no space to display any cells.
Note that this is just a guess, but it is the only scenario I can think of that would cause the behavior you described. The code you posted looks ok, although a bit more complicated than necessary.
There is no question that reloadData should be in viewWillAppear. That's where the Apple engineers put it when they created the UITableViewController class. So, to put it elsewhere, you have to believe you know better than they do.

Reusable TableView header views

For performance sake it is usual to reuse UITableView' cells.
Is there a way to do the same thing with TableView header' views?
I am talking about the ones that are returned with delegate's method:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
I tried to do the following which doesn't seem to be working as expected:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *CellIdentifier = #"Header";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil) {
cell = [self getHeaderContentView: CellIdentifier];
}
return cell;
}
Is there a way to reuse header' views?
The reason Apple built in the ability to reuse tableview cells is because while the tableview may have many rows, only a handful are displayed on screen. Instead of allocating memory for each cell, applications can reuse already existing cells and reconfigure them as necessary.
First off, header views are just UIViews, and while UITableViewCell is a subclass of UIView, they are not intended to be placed as the view of a section header.
Further, since you generally will have far fewer section headers than total rows, there's little reason to build a reusability mechanism and in fact Apple has not implemented one for generic UIViews.
Note that if you are just setting a label to the header, you can use -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section instead.
For something more custom, such as a label with red text (or a button, image, etc), you can do something like this:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0,0, 320, 44)] autorelease];
UILabel *label = [[[UILabel alloc] initWithFrame:headerView.frame] autorelease];
label.textColor = [UIColor redColor];
label.text = [NSString stringWithFormat:#"Section %i", section];
[headerView addSubview:label];
return headerView;
}
You can implement that by creating UITableViewHeaderFooterView class
it is subclass of UIView
You also need to create an individual XIB as it will not be created automatically with UITableViewHeaderFooterView creation.
Register Nib with tableview
[self.tblCart registerNib:[UINib nibWithNibName:#"CartHeaderView" bundle:nil] forHeaderFooterViewReuseIdentifier:#"CartHeader"];
Now You can Access that in viewForHeaderInSection
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
CartHeaderView *sectionHeader=[tableView dequeueReusableHeaderFooterViewWithIdentifier:#"CartHeader"];
return sectionHeader;
}
Note :
To set background color you will need to create a subview with same frame as section header and set color for that view.
you can follow
Changing the background color on a UITableViewHeaderFooterView loaded from a xib says to use contentView.backgroundColor instead
A simple yet effective solution:
#interface SectionedTableViewController ()
#property (nonatomic, strong) UINib* sectionHeaderNib;
#property (nonatomic, strong) NSMutableArray* sectionHeaders;
#end
#implementation SectionedTableViewController
#synthesize sectionHeaderNib = sectionHeaderNib_;
#synthesize sectionHeaders = sectionHeaders_;
- (void) viewDidUnload
{
self.sectionHeaders = nil;
[super viewDidUnload];
}
- (NSMutableArray*) sectionHeaders
{
if (!sectionHeaders_)
self.sectionHeaders = [NSMutableArray array];
return sectionHeaders_;
}
- (UINib*) sectionHeaderNib
{
if (!sectionHeaderNib_)
self.sectionHeaderNib = [UINib nibWithNibName: NSStringFromClass(YourHeaderView.class) bundle: nil];
return sectionHeaderNib_;
}
- (YourHeaderView*) dequeueHeader
{
return [self.sectionHeaders firstObjectPassingTest: ^(id obj) { return (BOOL) ([obj superview] == nil); }];
}
- (NSString*) sectionHeaderTitleForSection: (NSInteger) section
{
return nil;
}
- (UIView*) tableView: (UITableView*) tableView viewForHeaderInSection: (NSInteger) section
{
YourHeaderView* headerView = [self dequeueHeader];
if (!headerView)
{
headerView = [YourHeaderView instanceFromNib: self.sectionHeaderNib];
[self.sectionHeaders addObject: headerView];
}
return headerView;
}
#end