creating custom tableview cells in swift
Thanks for all the different suggestions, but I finally figured it out. The custom class was set up correctly. All I needed to do, was in the storyboard where I choose the custom class: remove it, and select it again. It doesn't make much sense, but that ended up working for me.
How to create custom cells 100% programmatically in Swift?
I see several errors in your cell.
Add subviews to
contentView
, not directly to cell:contentView.addSubview(cellView)
cellView.addSubview(labelView)The same is necessary for constraints:
NSLayoutConstraint.activate([
cellView.topAnchor.constraint(equalTo: contentView.topAnchor),
cellView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
cellView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
cellView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
])Views created in code need to set
translatesAutoresizingMaskIntoConstraints = false
,let cellView: UIView = {
let view = UIView()
view.backgroundColor = .systemRed
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let labelView: UILabel = {
let label = UILabel()
label.text = "Cell 1"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()- There are no constraints for your label.
How do I create a custom view in a custom table view cell?
The answer to you question is "Yes, you should put checkbox settings to another place. Particularly I would suggest you to move it to CustomTableViewCell
class"
There is an opinion, that good Object-oriented software design is based on SOLID principles.
SOLID is an acronym. And S stands for Single responsibility principle.. Simply saying - one class should be responsible for one thing and this responsibility should be encapsulated by the class.
In your case ViewController
takes responsibility for the Cell
s subview layouting and adjustments. Which breaks at least ~S~ in SOLID
P.S. To be honest I am a bit afraid to write this answer, because of often arguments about good software design.
Creating custom table View with Cell properties programmatically
In setUpUI()
method of your RoomViewController class, set tableView's rowHeight
to UITableView.automaticDimension and estimatedRowHeight
to 100.
import UIKit
class RoomViewController: UIViewController {
private func setUpUI() {
view.backgroundColor = .white
title = "Room List "
view.addSubview(tableView)
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableView.automaticDimension
// create constraints
tableView.topAnchor.constraint(equalTo:view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo:view.safeAreaLayoutGuide.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo:view.safeAreaLayoutGuide.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
// Creating constrain for Indecator
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(activityIndicator)
activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
activityIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
And add UIStackView in the RoomCellTableViewCell
class as bellow:
import UIKit
class RoomCellTableViewCell: UITableViewCell {
private var stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: topAnchor),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
stackView.leftAnchor.constraint(equalTo: leftAnchor),
stackView.rightAnchor.constraint(equalTo: rightAnchor)
])
stackView.addArrangedSubview(createdAtLabel)
stackView.addArrangedSubview(isOccupiedLabel)
stackView.addArrangedSubview(maxOccupancyLabel)
// stackView.addArrangedSubview(idLabel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
How to add a custom cell of uitableviewcell type as tableview header?
You should use the UITableViewDelagates and Datasource functions for the sections.
Try this:
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if let headerView = tableView.dequeueReusableCell(withIdentifier: "CustomCellHeader") as? CustomCellHeader {
cell.configure(tit: model.title)
cell.delegate = self
return headerView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 110
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return anyArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell") as? TableCell {
cell.configureCell(with: model.data[indexPath.row])
return cell
}
}
You can add number of sections according to your choice and also can set the header's cell and the other's cell height separately.
Unable To Create a Custom Table View Cell programatically, Swift
I have come to know that without a NIB file, awakeFromNib won't be invoked, so the view wasn't being added.
By looking at this Stackoverflow question I modified the code to the below and it worked.
class AppointmentTVCell: UITableViewCell {
var caseId = UILabel()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//Do your cell set up
caseId.frame = CGRect(x: 0, y: 50, width: 100, height: 30)
caseId.text = "Hello"
caseId.font = UIFont(name:"HelveticaNeue-Bold", size: 16)
contentView.addSubview(caseId)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Using custom XIB in table view cell
You can use 2 ways:
Create UITableViewCell (better)
1) Change UIView to UITableViewCell
class CustomTableViewCell: UITableViewCell {
...
class var identifier: String {
return String(describing: self)
}
}
2) Register your cell
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerNib(UINib(nibName: CustomTableViewCell.identifier, bundle: nil), forCellReuseIdentifier: CustomTableViewCell.identifier)
...
}
3) Use cellForRow(at:)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier) as! CustomTableViewCell
cell.username.text = user.username
return cell
}
OR Add view as subview to cell (only in rare cases)
1) Add this to UserView
class UserView: UIView {
...
class func fromNib() -> UserView {
return UINib(nibName: String(describing: self), bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UserView
}
}
2) Use cellForRow(at:)
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "UserTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? UserTableViewCell else {
fatalError("The dequeued cell is not an instance of UserTableViewCell.")
}
let userView = UserView.fromNib()
let user = users[indexPath.row]
userView.username.text = user.username
//Use frame size, but for me better to add 4 constraints
userView.frame = CGRect(x: 0, y: 0, width: cellWidth, height: cellHeight)
cell.contentView.addSubview(UserView)
return cell
}
Can you make a TableView in a custom cell?
You can absolutely put a UITableView inside UITableViewCells
Where to put .delegate = self depends how you created the cell.
If you created it programmatically then use override init
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
tableView = UITableView()
tableView.delegate = self
tableView.dataSource = self
}
If however your load the cell from nib or storyboard then use initWithCoder
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
tableView = UITableView()
tableView.delegate = self
tableView.dataSource = self
}
return self;
}
Just a note, you are setting yourself up for a bumpy road. Its entirely possible nonetheless so good luck!
Insert Custom Cell into TableView
From my practice it is better to create custom type of cell. And add this type as a property to your PostViewModel. After that you can recognize what type of cell you should to dequeue. For example:
// Type of custom cell
enum PostsType {
case postCell
case loginCell
}
struct PostViewModel {
let type: PostsType
// another View model data
}
class ViewController: UITableViewController {
var posts: [PostViewModel] = [] {
didSet {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellType = posts[indexPath.row].type
switch cellType {
case .loginCell:
return tableView.dequeueReusableCell(withIdentifier: "LoginCell", for: indexPath)
case .postCell:
return tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath)
}
}
}
Related Topics
How to Convert a Date String With Optional Fractional Seconds Using Codable in Swift
How to Get the Count of a Swift Enum
How to Make a Weak Protocol Reference in 'Pure' Swift (Without @Objc)
Swift Lazy Instantiating Using Self
Why Constant Constraints the Property from a Structure Instance But Not the Class Instance
What Is the Cause of This Type Error
Fix Warning "C-Style For Statement Is Deprecated" in Swift 3
What Is Difference Between Optional and Decodeifpresent When Using Decodable For Json Parsing
Difference Between Functions and Closures
Waiting Until the Task Finishes
How to Set Associated Objects in Swift
Nsurlsession Concurrent Requests With Alamofire
Unexpected Non-Void Return Value in Void Function (Swift 2.0)
Check Password String Strength Criteria in Swift
Value of Type 'Storagemetadata' Has No Member 'Downloadurl'