Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up UITableView within a UIViewController created on a .xib file

I have a class like this:

@interface ExerciseLogDetails : UIViewController<UIActionSheetDelegate, UITableViewDelegate, UITableViewDataSource> {

where I am trying to display some elements followed by a UITextView. The UITextView element is created on Interface Builder. When executing this code:

- (void)viewDidLoad {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds       style:UITableViewStylePlain];
tableView.dataSource = self; 
tableView.delegate = self;
[self.view addSubview:self.tableView];
}

a table shows, but not the one I configured in Interface Builder. It is completely blank and unformatted. How can I access my table and populate it progrmmatically with data?

Thank you!

like image 968
MrSueko Avatar asked Jul 13 '12 06:07

MrSueko


People also ask

How do I register a nib file in Swift?

viewDidLoad() let nib = UINib(nibName: "MyCustomCell", bundle: nil) myTable. register(nib, forCellReuseIdentifier: "MyCustomCell") myTable. dataSource = self } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if let cell = tableView.

How to use ViewController as XIB in Swift?

Once you decided on a type of UI Controller (View, TableView, CollectionView, etc.), go into File > New > File (⌘N) and select Cocoa Touch Class . Click next. Now we are going to select the subclass and give the new UI Element a name. Let's call it RateMe, with the type of UIViewController .


2 Answers

Several of the tips on this thread helped me create this. I am going to offer some more complete code files in order to help others as well:

Step 1. Drag your UITableView onto your View Controller either in Storyboards or XIBs. In my example I am using a story board.

Step 2: Open your ViewController (in my case its just DefaultViewController) and add the two delegates for the UITableView: UITableViewDelegate and UITableViewDataSource. Also add a simple data source for population and the UITableView IBOutlet.

DefaultViewController.h

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) NSMutableArray *newsArray;

@end

Step 3: Open your implementation file (DefaultViewController.m) and add the following:

#import "DetailViewController.h"

@interface DetailViewController ()
- (void)configureView;
@end

@implementation DetailViewController

@synthesize newsArray;
@synthesize tableView;

#pragma mark - Managing the detail item

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self configureView];
}

- (void)configureView
{
    // Update the user interface for the detail item.
    self.newsArray = [[NSMutableArray alloc] initWithObjects:@"Hello World",@"Goodbye World", nil];
}



- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark UITableViewDelegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // typically you need know which item the user has selected.
    // this method allows you to keep track of the selection

}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
           editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{

    return UITableViewCellEditingStyleDelete;
}

// This will tell your UITableView how many rows you wish to have in each section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.newsArray count];
}

// This will tell your UITableView what data to put in which cells in your table.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifer = @"CellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifer];

    // Using a cell identifier will allow your app to reuse cells as they come and go from the screen.
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifer];
    }

    // Deciding which data to put into this particular cell.
    // If it the first row, the data input will be "Data1" from the array.
    NSUInteger row = [indexPath row];
    cell.textLabel.text = [self.newsArray objectAtIndex:row];

    return cell;
}

@end

Step 4: Goto your Storyboards or XIB and select your UITableView and drag the datasource and delegate outlets onto your DefaultViewController to wire them up. Also you will need to wire up the Referencing Outlet for the UITableView to your IBOutlet tableView object you created in your header file.

Once this is finished you should be able to run it and the sample data will be in place.

I hope this along with the other tips on this thread will help others setup a UITableView from scratch on a ViewController.

like image 85
Flea Avatar answered Dec 07 '22 22:12

Flea


If you configured a tableView in IB you shouldn't also create one programmatically, you should create @property (nonatomic, retain) IBOutlet UITableView *tableView; and connect it to the tableView you configured in IB.
Try to set a breakpoint in the tableView's
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
delegate method to see if this method get called.

From Apple UITableView docs:

A UITableView object must have an object that acts as a data source and an object that acts as a delegate; typically these objects are either the application delegate or, more frequently, a custom UITableViewController object. The data source must adopt the UITableViewDataSource protocol and the delegate must adopt the UITableViewDelegate protocol. The data source provides information that UITableView needs to construct tables and manages the data model when rows of a table are inserted, deleted, or reordered. The delegate provides the cells used by tables and performs other tasks, such as managing accessory views and selections.

As u can see if u don't set a dataSource to your tableView, the tableView will not know how and what to display, so nothing will happen.
You can set one by calling tableView.dataSource = self; or in IB drag from your tableView to the file's owner (that is your viewController that must implement the UITableViewDataSource Protocol)

There are two methods in the UITableViewDataSource protocol that your dataSource must implement:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  

and

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:  (NSIndexPath *)indexPath  

If u won't implement those methods u will get a compiler warnings.
You can have more control on how the tableView will look if you implement the UITableViewDelegate protocol - like row/header/footer height, selections and more...

From Apple UITableView docs:

UITableView overrides the layoutSubviews method of UIView so that it calls reloadData only when you create a new instance of UITableView or when you assign a new data source. Reloading the table view clears current state, including the current selection. However, if you explicitly call reloadData, it clears this state and any subsequent direct or indirect call to layoutSubviews does not trigger a reload.

ReloadData get called when the tableView is created or when you assign a new dataSource (or when you explicitly call it of course..).
This is when the tableView needs to know what to display (how many sections?, how many rows?, and which cell to display?) - So this is when numberOfRowsInSextion method called.

like image 42
Eyal Avatar answered Dec 07 '22 23:12

Eyal