Sebastian Boldt
Sebastian Boldt

Reputation: 5321

Best approach to add Static-TableView-Cells to a UIViewcontroller?

I want to add a tableview-look-a-like-login to my app, but it seems to be not that easy to implement. I tried to accomplish my goal using more then one approach, but i am not sure about which solution is the best.

For example, Dropbox and Facebook have a login page like this.

Here are my 3 approaches :

  1. I added 2 UITextfields to my View (no border) and placed a . png behind, which looks like a tableviewcell. ( Not the best approach cause i want to use real tableviews )

  2. I added a Container View to my ViewController placed a tableview with static Table Views inside. The Problem here is, that i dont know how to access the information inside my viewcontroller?

  3. I added a tableview to my ViewController and used dynamic cells with it. Connected the outlets for delegate and datasource to my viewcontroller and initialized them with the delegate and datasource methods. The Problem here is, that i can not use static table views inside a uiviewcontroller.

Is there any better way of solving this problem ? I would really like to know how to do this in a more elegant way.

EDIT:

A ContainerViewController basically solved this issue for me some month ago. After embedding one into the main controller you can access it through the prepareForSegue function and define a protocol-based interface for that specific controller to interact with the embedded controller.

Upvotes: 7

Views: 6991

Answers (6)

etipton
etipton

Reputation: 164

I found Can's solution to be the best / easiest, but unfortunately it breaks in XCode 5.1 --

I found a workaround which builds off the same basic idea, but unfortunately requires a little more involvement: http://www.codebestowed.com/ios-static-tableview-in-uiviewcontroller/

To summarize, you can add TableViewCells directly to views (and create IBOutlets from them, etc), but in order for them to get "moved" to the TableView properly, you need to remove them from the view in code, and you also need to set Auto-Layout constraints in IB.

Upvotes: 0

Can Poyrazoğlu
Can Poyrazoğlu

Reputation: 34780

If you want to use static cells inside a regular UIViewController, just add the static cells and design them the way you like in interface builder, then connect the table cells as strong IB outlets (weak won't work, make sure they are strongly referenced). This will work flawlessly if you have a few table cells. Then set the view controller as the data source of the tablet view, implement -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section to return the number of cells and implement -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to return your strongly referenced cell instance for the specified index path. I've used this method for a simple table view in my view controller that had four cells and it is working perfectly. For a large-dynamic data set, I definitely do not recommend this approach but for small, static tables, this does the job right.

Upvotes: 3

RileyE
RileyE

Reputation: 11074

Disclaimer - This answer will work for any size of UITableView, but if you're just making a login view, Tom's answer will work quite well.

I'm not sure if this will help, but what I did for this was create my own UITableView-esque subclass with a UITableViewCell-esque subclass as well.

This may not be what you want to hear, but I find what I made to be really helpful, since I've used it a number of times now. Basically, you have a UIView with the stylistic approach for the different types (10.0f - 20.0f cornerRadius and a 1px border (divide by UIScreen's scale property for retina). As for the cell, you'll want to have a full sized UIButton on it that responds to your table view for the touch events either with a delegate or by setting the target and tag inside your table view's class.

Last, you'll have a delegate system just like the UITableView for your information for building the specific tables.

In short, you'll need:

  • 2 UIView subclasses (TableView and TableViewCell)
  • 2 Delegates/Protocols (TableViewDataSource and TableViewDelegate)

Optionally

  • 1 Delegate (TableViewCellResponseDelegate)
  • 1 NSObject Subclass (Contains all of the information needed in each cell - Ease of use)

Upvotes: 1

Mike Pollard
Mike Pollard

Reputation: 10195

If you go with your option 2) using a storyboard and have a ContainerView containing your own subclass of UITableViewController with static cells then you can implement the prepareForSegue: method in your parent ViewController to take a reference to the UITableViewController (it'll be the destinationController of the segue) and also to pass itself down to the UITableViewController subclass if necessary (which should hold onto it with a weak reference).

Upvotes: 1

rdelmar
rdelmar

Reputation: 104082

I think your approach 2 is the best. If you need to access information in the table view controller, from your UIViewController (which will be the parent view controller), you can get a reference to that table view controller with self.childViewControllers.lastObject. In the viewDidLoad method of the UIViewController subclass, you could set yourself as the delegate of the table view with this line if you want:

[[(UITableViewController *)self.childViewControllers.lastObject tableView] setDelegate:self];

That way, you could implement the tableView:didSelectRowAtIndexPath: method in the view controller, which will get the information I'm guessing you need.

Upvotes: 1

Tom van Zummeren
Tom van Zummeren

Reputation: 9220

I have an idea how to solve this. I think it's a clean way to do so. You do not need storyboard for this controller.

Make your controller subclass UITableViewController like so:

@interface YourViewController : UITableViewController

Then in your viewDidLoad you create the instances of the cells:

- (void) viewDidLoad {
    usernameCell = [YourTextFieldCell new];
    passwordCell = [YourTextFieldCell new];
}

The YourTextFieldCell is of course your own subclass of a UITableViewCell, which could be something like this:

@implementation YourTextFieldCell {
    UITextField textField;
}
- (id) init {
    self = [super init];
    if (self) {
        // Adjust the text's frame field to your liking
        textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
        [self addSubview:textField];
    }
}
// A getter method to access the textfield from the outside
- (UITextField *) textField {
    return textField;
}

@end

Back in YourViewController:

- (NSInteger) tableView:(UITableView *) tv numberOfRowsInSection:(NSInteger) section {
    return 2;
}
- (UITableViewCell *) tableView:(UITableView *) tv cellForRowAtIndexPath:(NSIndexPath *) indexPath {
    if (indexPath.row == 0) {
        return usernameCell;
    } else if (indexPath.row == 1) {
        return passwordCell;
    }
    return nil;
}

Do you get where I am going with this? This is how I think you should do it! Good luck!

Upvotes: 2

Related Questions