views:

291

answers:

2

Hi,

I have a UITableView in grouped style in my iPhone app. Now I want to customize the section headers with an Image, a label and an activity indicator.

To do this I created a new UIViewController subclass and a XIB file. I added the UIImageView, UILabel and UIActivityIndicatorView as IBOutlet properties to the ViewController and wired them to controls I put into the XIB in Interface Builder.

In the class where my UITableView is made I setup the section headers (two, both instances of the ViewController defined above) and set their properties (image and text). Then I return the ViewControllers view in the tableView delegate:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (section == 0) {
        return [favoritesSectionHead view];
    } else {
        return [serverlistSectionHead view];
    }
}

This displays the view as I defined it in Interface Builder, without the custom image and text. I know why this happens (the view of a ViewController is created when first needed, in my code this is when I return it in the viewForHeaderInSection method --> when I try to setup the custom values the view is still nil) but I don't know how to fix this.

Can you help me? What do I have to do to init the view before my returns? The UITableView docs tell me not to call "loadView" manually ...

Thanks in advance, Mark.

A: 

I had to add a NSString property to my section view controller. In the viewDidLoad I assigned this string to the UILabel text property, now it is working.

Mark Gibson
A: 

I had the same problem with the view = (null). It is all about the "Delegates". My tableView was working fine, and all my UITableView Delegate methods were properly working, however the viewForHeaderInSection: would not implement.

I discovered that Xcode was letting me build with a weak-linked reference with the TableView, which was not sufficient for the "viewForHeaderInSection:" method.

I also discovered that Xcode will easily push a "Coded" custom view from within the viewForHeaderInSection: method, with this same weak reference, but using IB, the link has to be more established. Takes a little more work, but offers a much better experience once you get it down to build much more complicated objects.

I used: NSLog([NSString stringWithFormat:@"%@", self.headerView]); to verify that the view was outputting as (null).

The viewForHeaderInSection: method is called first, if nil or null, the tableView calls the "titleForHeaderInSection:" next. (you can also use this to your advantage).

Make sure your setup is correct and makes sense on how the objects work with one another.

Sample Steps that worked for me: (.h)


1. Properly setup a viewController, and declare the tableView delegation methods. I was using the generic UITableViewController, didn't work for me inside complex TabBar, with UINavigationControllers.

    @interface YourViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UIAlertViewDelegate, UIAccelerometerDelegate> {
  1. Create all the IBOutlets that will be on your view:

    IBOutlet UITableView *myTableView; IBOutlet UIView *yourCustomHeaderView; IBOutlet UIImageView *yourImageOnCustomView;

  2. Assign Memory Allocation Assignment: @property(nonatomic,retain) IBOutlet UITableView *yourTableView;
    @property(nonatomic,retain) IBOutlet UIImageView *yourCustomHeaderView; @property(nonatomic,retain) IBOutlet UIImageView *yourImageOnCustomView;

(.m)


  1. Synthesize your Variables:

    @synthesize yourTableView, yourCustomHeaderView, yourImageOnCustomView;

  2. Implement all your standard TableView delegate required methods, plus:

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    //Intialize the header View to present:
    UIView *headerView;
    
    
    //Display Section Headers for rows:
    if (section == 0) {headerStatBar = self.yourCustomSectionHeaderView1;}
    if (section == 1) {headerView = self.yourCustomSectionHeaderView1;} 
    if (section == 1) {headerView = self.yourCustomSectionHeaderView1;}
    
    
    //Return the view to the Table:
    return headerView;
    }
    
  3. Make all your Connections in IB, easiest way:

3-1. View your objects with the "LIST VIEW", provides better understanding and object hierarchy 3-2. Right-Click your "File's Owner", to reveal all your IBOutlets; 3-3. Drag all your IBOutlet connections from the File's Owner to the Object they control; i.e. (yourTableView -> tableView) or yourCustomHeaderView -> customized view that you designed) and (yourImage -> custom UIImageView that you dropped on your custom View.


Now that the connections are made, you have "FULL" control over aspect of each item, by setting any property of that item, such as self.yourCustomHeaderView.background = [UIColor redColor]; etc....

** Make sure you Drag from the "TableView" to the "File's Owner" to set the table's (delegate) and (datasource) back to the file's owner; which happens to be where all your tableView delegate methods are!


This is just the simplest of steps, you can make the view as complex as you need it, one of my viewForHeaderInSection: views has 40+ IBoutets for all the views, which include buttons, images, labels, other views, etc...


Really tried to keep all the code in the 'code blocks', just wouldn't work, but you can still read it.

Newbyman
Hi Newbyman, thanks for your very detailed answer.As you can see in the answer above my problem was a different one (I didn't follow the MVC pattern correctly), but I am sure someone else will have the problem your solution fits to and will be glad to find it here!
Mark Gibson