By default when I drag out a TableViewController in IB the tableview takes up all the screen, and there is no way to add a UIView that stays in place even when the user scrolls the tableview (If i Say add a UIView with some buttons, then when I scroll the tableview that UIView will scroll as well.)
My program uses a UITableViewController subclass to control the tableview, what´s the easiest way of having a top bar that stays static even when the user scrolls?
Starting in iOS7, there is additional space at the top of my UITableView 's which have a style UITableViewStyleGrouped . The tableview starts at the first arrow, there are 35 pixels of unexplained padding, then the green header is a UIView returned by viewForHeaderInSection (where the section is 0).
Simple, instead of using a UITableViewController just use a UIViewController with a UITableView placed inside it. (leaving room for you to add your secondary view above or below the table) That way, you can let the view controller's view take up the entire screen, and manually define the frame of the table view within it. There will be a little bit of rearranging required but will suit your needs.
The only real differences you need to be aware of, is that you'll need to make your view controller conform to both the UITableViewDelegate, and UITableViewDatasource protocols, as well as declaring the outlet for the table view yourself.
@property (weak,nonatomic) IBOutlet UITableView *tableView;
It is also important to keep in mind that there a few functions that are only available on UITableViewController like clearsSelectionOnViewWillAppear
, but you can always replicate them yourself.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathsForSelectedRows animated:YES];
}
The approach I recommend (and I think this is the design pattern Apple encourages) is to use an embed segue to insert your table view controller into a parent controller that contains your additional views. This helps keep things modular and helps make the overall app structure easy to understand.
The basic steps are as follows:
prepareForSegue
method, check for your embed segue's identifier and do any additional wiring. The view controller and view relationships are established automatically, but you might want configure the table view controller and keep a reference to it.Programmatically, using Swift constraints. In my opinion, this solution is cleaner:
import UIKit
class SettingsController : UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView : UITableView = {
let t = UITableView()
t.translatesAutoresizingMaskIntoConstraints = false
return t
}()
override func viewDidLoad() {
super.viewDidLoad()
// set a background color so we can easily see the table
self.view.backgroundColor = UIColor.blue
// add the table view to self.view
self.view.addSubview(tableView)
// constrain the table view to 120-pts on the top,
// 32-pts on left, right and bottom (just to demonstrate size/position)
tableView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 32.0).isActive = true
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 120.0).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -32.0).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -32.0).isActive = true
// set delegate and datasource
tableView.delegate = self
tableView.dataSource = self
// register a defalut cell
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
// Note: because this is NOT a subclassed UITableViewController,
// DataSource and Delegate functions are NOT overridden
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 25
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "\(indexPath)"
return cell
}
// MARK: - Table view delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// etc
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With