Reputation: 17
In swift playground (not in a project) Could you please give me a hint about how to do this please?enter image description here
Upvotes: 0
Views: 1008
Reputation: 9039
Full credit to @Rob, this is a tweak of his answer, but after trying to directly add the cell to a table view to no avail (cells seem to ignore explicit sizing), I reduced his view controller to a generic one for ease of re-use.
class DashboardViewController<T: UITableViewCell>: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(T.self, forCellReuseIdentifier: "Cell")
// set it up to let auto-layout resize the cell
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! T
configure(cell)
return cell
}
var configure: ((T) -> ())!
static func with(configuration: ((T) -> ())!) {
let controller = DashboardViewController<T>()
controller.configure = configuration
PlaygroundPage.current.liveView = controller
}
}
// usage:
DashboardViewController<MyCustomCell>.with() { cell in
let model = MyCellModel()
cell.model = model }
Upvotes: 1
Reputation: 437552
You have to implement init(style:reuseIdentifier:)
in your custom class to define subviews and constraints programmatically.
Thus:
import UIKit
import PlaygroundSupport
class CustomCell: UITableViewCell {
weak var label1: UILabel!
weak var label2: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let label1 = UILabel()
label1.translatesAutoresizingMaskIntoConstraints = false
label1.font = .preferredFont(forTextStyle: .title1)
label1.backgroundColor = #colorLiteral(red: 0.572549045085907, green: 0.0, blue: 0.23137255012989, alpha: 1.0)
label1.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
contentView.addSubview(label1)
self.label1 = label1
let label2 = UILabel()
label2.translatesAutoresizingMaskIntoConstraints = false
label2.font = .preferredFont(forTextStyle: .title1)
label2.backgroundColor = #colorLiteral(red: 0.0901960805058479, green: 0.0, blue: 0.301960796117783, alpha: 1.0)
label2.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
contentView.addSubview(label2)
self.label2 = label2
NSLayoutConstraint.activate([
label1.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
label2.leadingAnchor.constraint(equalTo: label1.trailingAnchor, constant: 10),
contentView.trailingAnchor.constraint(equalTo: label2.trailingAnchor, constant: 10),
label1.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
label2.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
contentView.bottomAnchor.constraint(equalTo: label1.bottomAnchor, constant: 10),
contentView.bottomAnchor.constraint(equalTo: label2.bottomAnchor, constant: 10),
label1.widthAnchor.constraint(equalTo: label2.widthAnchor)
])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And then you'd have a standard UITableViewController
which registers this class and uses it:
class ViewController: UITableViewController {
var objects: [String] = {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return Array(0 ..< 1000).flatMap { formatter.string(from: NSNumber(value: $0)) }
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
// set it up to let auto-layout resize the cell
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.label1.text = objects[indexPath.row]
cell.label2.text = "Row \(indexPath.row)"
return cell
}
}
PlaygroundPage.current.liveView = ViewController()
Now that just creates a simple view like this:
That's not terribly pretty, but I set the background colors like I did, just so you can see that the frames are set appropriately. You'd obviously adjust your init(style:reuseIdentifier:)
to create subviews more to your liking.
If you want the standard cell, then you don't need to have a custom cell subclass, but you can just use UITableViewCell
:
import UIKit
import PlaygroundSupport
class ViewController: UITableViewController {
var objects: [String] = {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return Array(0 ..< 1000).flatMap { formatter.string(from: NSNumber(value: $0)) }
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = objects[indexPath.row]
return cell
}
}
PlaygroundPage.current.liveView = ViewController()
On the iPad, that yields:
On Playground in Xcode, it yields:
Upvotes: 5