32

I have an existing ViewController + xib in my project, and now I want to add a UITableView with static cells, like this:

TableView with static cells

But when I drag a UITableView onto my screen I don't have the "Content > Static" menu in the Attributes Inspector.

I've tried making my controller subclass UITableViewController, but that doesn't help -- I still don't get the option to use static cells in Attributes Inspector.

I've looked around on StackOverflow but haven't found any existing answers to this question. All the existing questions relate to Storyboards (which I'm not using) instead of xib files.

My guess is that Xcode does some kind of magic when you add a UITableViewController to a storyboard, but not when you change an existing xib to inherit from UITableViewController.

Any advice how how to add a table view with static cells to an existing xib?

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
Kyle Fox
  • 3,133
  • 4
  • 23
  • 26

3 Answers3

45

Static table view cells are only available when using storyboards. However, if you aren't using storyboards for your entire UI you can still use them for individual screens instead of a collection of screens.

To do this you can create a UIStoryboard file with a single view controller on it that has it's File's Owner set to your custom view controller subclass. Set the VC's identifier to some value. When you want to display this, get the storyboard and then instantiate your view controller subclass by creating the VC from your storyboard.

UIStoryboard *tableViewStoryboard = [UIStoryboard storyboardWithName:@"your storyboard" bundle:nil];
CustomViewController = [tableViewStoryboard instantiateViewControllerWithIdentifier:@"custom identifier"];

You can present this VC as usual in your app.

This is a great way to start using storyboards without having to convert your entire app to use them.

Colin Humber
  • 1,395
  • 1
  • 16
  • 23
28

This is doable without storyboards:

  1. your controller must adopt protocols for tableview delegate and source...UITableViewDelegate, UITableViewDataSource
  2. Add a table view to your .xib; set the table view's style to "grouped"
  3. Connect the table to a property in your controller (let's call it "yourTableView")
  4. Add table view cells to the .xib as separate views...i.e. not as subviews of the table view...they'll be free floating in the .xib. (see example image below)
  5. Add controls / labels etc to the table cells.
  6. Assign unique strings to the "Identifier" field in Attributes for each table view cell.
  7. Connect the table cells to other properties in the controller (sliderCell, switchCell, etc)
  8. Connect the send events for the cells' controls to IBAction-ed methods in the controller - (IBAction) handleSliderCell, etc.
  9. In the viewDidLoad method of your controller, assign the delegate and source of the table view to the controller (self.yourTableControl.delegate = self; self.yourTableControl.dataSource = self;)
  10. implement numberOfSectionsInTableView, numberOfRowsInSection, and cellForRowAtIndexPath in the controller
  11. in tableView:cellForRowAtIndexPath:, return yourFirstCell, yourSecondCell, etc pointers for appropriate indexPath values

Events for controls for the table cells should go to your handler routines...

Example for step 4: xib

BVB
  • 5,380
  • 8
  • 41
  • 62
  • 1
    Is there any advantage of this approach if one is just targeting iOS versions where storyboards are supported? – philwilks Aug 14 '14 at 08:50
  • Doesn't work for me. I get a **could not load nib in bundle** error. And I can't register a nib explicitly because there are no classes associated with the cells created in the IB. So I just created subclasses of `UITableViewCell` and added them to the cells and tried again but still no luck. Same error comes up. – Isuru Sep 14 '14 at 14:59
  • 1
    @philwilks - the advantage of this over storyboards is that you get config management benefits from not using storyboards - so if multiple devs are updating the UI you wont get in such a muddle – Charlie S Dec 15 '16 at 10:40
  • Is set the ```Identifier``` useful? Not reusable right? – William Hu Sep 05 '17 at 09:49
0

To expand on BVB's answer, when it comes to number 10, here are the Swift 3 snippets for your tableview delegate methods. Be sure to add outlets to all your cells in the xib.

When you manually create your table view sections, remember that indexPath is equal to a 2 dimensional array representing your table structure. for example, when indexPath is passed to tableView(cellForRowAt indexPath: IndexPath) is equal to [1][0], your cell will be placed in the first position of the second section.

Values can be pulled out of indexPath with the properties indexPath.row and indexPath.section. Using these values, you can manually construct your sections from your IBOutlets in whichever order you prefer.

@IBOutlet var is_enabled: UITableViewCell!
@IBOutlet var is_public: UITableViewCell!

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch(section){
        case 0:
            return "Cell 1"
        case 1:
            return "Cell 2"
        default: return ""

    }
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 2
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("index path here", indexPath)
    if(indexPath.section == 0)  {
        return is_enabled
    }
    else if(indexPath.section == 1) {
        return is_public
    } else {
        return is_enabled
    }
}
thexande
  • 1,645
  • 16
  • 23