问题
I have a class set up as follows:
class SettingsController: UITableViewController {
I would like to be able to add constraints to the UITableView so that there is equal spacing either side of the table (it is currently a full width table, so a little ugly on iPad).
I have read that I can't add constraints to a UITableViewController
, and instead I must add a UIViewController
to my class, add a UITableView
to that, and then I should be able to add the constraints to the TableView.
I've amended the class and defined the UITableView
on the next line. So here are my first two lines now:
class SettingsController: UIViewController {
var tableView = UITableView()
Further down, I have this code to attach the TableView to the UIView
:
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(tableView)
}
The app builds successfully but when trying to access this view, the screen is blank, so I've not been able to attempt the constraints part yet (the screen does display the data correctly if I revert what I've described).
Many of my existing functions within this class reference tableView
for passing in the data/setting the number of rows etc, but it seems I've not done something right... is there a piece I'm missing?
回答1:
Here is a simple example of programmatically creating and adding a table view to a "normal" view:
//
// SettingsController.swift
//
// Created by Don Mag on 7/25/17.
//
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
}
}
You should be able to run this without edits, and get a result along these lines: It is a very simple example, so should be pretty easy to see what's going on.
If you already have your (I'm assuming, complex) Settings UITableViewController
class working, it should be pretty straight-forward to follow this skeleton and convert yours to a UIViewController
+ UITableView-as-subview
.
Alternatively, you can load your existing UITableViewController
as a child view controller, and add its view (the tableview) as a subview.
回答2:
So, it looks like you need to back up a step and not try to somehow embed a a UIViewController inside a TableViewController. The recommendation you mentioned means that your SettingsController should subclass UIViewController and you should add a UITableView to that.
Adding constraints to a UITableView will treat you much nicer than trying to play with a UITableViewController at all.
Edit
You should be able to implement the constraints before you have any data. You'll just see an empty table view, but it will still show rows. Sometimes it's easier to play with constraints if you can see what you're dealing with. When you create your tableView, you can do it with:
var tableView = UITableView(frame: self.view)
at least to help you get your bearings.
So after you implement the constraints you need, it looks like all you'd be missing is setting the tableView's delegate and dataSource and extending your view controller to implement those methods. Then you should have data, and you can bask in the glory of your hard work.
回答3:
I'm just showing another way to add constraints.
Here first you need to set view.translatesAutoresizingMaskIntoConstraints = false
and do following
// align tableView from the left and right
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-8-[view]-8-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": tableView]))
// align tableView from the top and bottom
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[view]-8-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": tableView]))
It will give top, bottom, leading and trailing constraints to table view with respect to self.view (it's superview).
来源:https://stackoverflow.com/questions/45311714/how-to-add-programmatic-constraints-to-a-uitableview