A swift game of words, part II

In part I of this article I presented some bog basic code to generate a UITableView with the important stuff the drag and drop the main stay of the short paper. Of course without an editable tableview it was of very limited use so I thought I do a part II.

Your end goal for the UITableView should look like this with the ability to edit, insert and delete entries inline.

Image for post
Image for post

To start we need to setup a custom UITableCell class, with a UITextField inside it, the code looks like this.

class myTableViewCell: UITableViewCell, UITextFieldDelegate {let label:UITextField
var listItems:myItem? {
didSet {
label.text = listItems!.text
}
}
required init(coder aDecoder: NSCoder) {
fatalError(“init(coder:) has not been implemented”)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
label = UITextField(frame: CGRect.null)
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 16)
super.init(style: style, reuseIdentifier: reuseIdentifier)
label.delegate = self
label.contentVerticalAlignment = UIControlContentVerticalAlignment.center
addSubview(label)
}
let leftMarginForLabel: CGFloat = 16.0override func layoutSubviews() {
super.layoutSubviews()
label.frame = CGRect(x: leftMarginForLabel, y: 0, width: bounds.size.width — leftMarginForLabel, height: bounds.size.height)}func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if listItems != nil {
listItems?.text = textField.text!
}
return true
}
}

Missing here you need to create a second class to describe the class of variable that it is referencing myItem. The code for that looks like this.

class myItem: NSObject {
var text: String
init(text: String) {
self.text = text
}
}

Beyond this you need to review the initial code we added for the UITableView controller and update it to reflect the fact that you now want it to use a custom cell.

myTableView.register(myTableViewCell.self, forCellReuseIdentifier: “tableCell”)

That done you need to change the code that refers to this cell too.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {let cell = tableView.dequeueReusableCell(withIdentifier: “tableCell”, for: indexPath) as! myTableViewCelllet item = itemsToLoad[indexPath.row]
cell.listItems = item
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}

I wanted to be able to insert and delete rows in my table and added iOS 11 specific methods to do just that too.

func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?{
let editAction = UIContextualAction(style: .normal, title: “Insert”, handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in success(true)
let newE = myItem(text: “new”)
itemsToLoad.append(newE)
tableView.insertRows(at: [IndexPath(row: itemsToLoad.count-1, section: 0)], with: .automatic)
tableView.endUpdates()
})
editAction.backgroundColor = .blue
return UISwipeActionsConfiguration(actions: [editAction])
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
if itemsToLoad.count == 1 {
// abort
return UISwipeActionsConfiguration(actions: [])
}
let deleteAction = UIContextualAction(style: .destructive, title: “Delete”, handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in success(true)
itemsToLoad.remove(at: indexPath.row)
self.myTableView.reloadData()
})
deleteAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [deleteAction])
}

So you swipe right on the an existing row to insert a new one and you swipe left to remove a row.

But ok, there one drawback on this… you need to have added at least one row to start with and indeed you cannot delete all of them, else you won’t be able to add any more, hence the if abort clause.

Anyway I added 4 to be sure :) just to start out, add this line of code in your viewWillAppear method.

itemsToLoad += [myItem(text: “cat”), myItem(text: “sat”), myItem(text: “mat”), myItem(text: “rat”)]

And there you have it.

Written by

Coding for 35+ years, enjoying using and learning Swift/iOS development. Writer @ Better Programming, @The StartUp, @Mac O’Clock, Level Up Coding & More

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store