class MyCell: UITableViewCell { static let identifier: String = "MyCell" let label = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { label.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(label) let g = contentView.layoutMarginsGuide let b = label.bottomAnchor.constraint(equalTo: g.bottomAnchor) b.priority = .required - 1 NSLayoutConstraint.activate([ label.topAnchor.constraint(equalTo: g.topAnchor), label.leadingAnchor.constraint(equalTo: g.leadingAnchor), label.trailingAnchor.constraint(equalTo: g.trailingAnchor), label.heightAnchor.constraint(equalToConstant: 60.0), b, ]) label.font = .systemFont(ofSize: 16.0, weight: .regular) } } class AddRemoveTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { var myData: [String] = [] var myCounter: Int = 15 let tableView = UITableView() override func viewDidLoad() { super.viewDidLoad() tableView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(tableView) let g = view.safeAreaLayoutGuide NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: g.topAnchor), tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor), ]) myData = (1...myCounter).compactMap( { "Data Item \($0)" } ) navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Insert", style: .plain, target: self, action: #selector(addTapped(_:))) tableView.register(MyCell.self, forCellReuseIdentifier: MyCell.identifier) tableView.dataSource = self tableView.delegate = self let hv = UILabel() hv.backgroundColor = .yellow hv.text = "Header View" hv.frame.size.height = 40.0 tableView.tableHeaderView = hv tableView.refreshControl = UIRefreshControl() tableView.refreshControl?.addTarget(self, action: #selector(refresh(_:)), for: .valueChanged) view.backgroundColor = .red tableView.backgroundColor = .clear } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let c = tableView.dequeueReusableCell(withIdentifier: MyCell.identifier, for: indexPath) as! MyCell c.label.text = myData[indexPath.row] return c } @objc func addTapped(_ sender: Any?) { myCounter += 1 myData.insert("Inserted Data \(myCounter)", at: 3) tableView.insertRows(at: [IndexPath(row: 3, section: 0)], with: .automatic) } @objc func refresh(_ sender: UIRefreshControl) { DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { sender.endRefreshing() }) } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { myData.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) } } func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true } func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { return .delete } }