TIL: Swipe Actions and Pull to Refresh
Table of Contents
Swipe Actions
In my Poopmaster and RePNCalc apps, I had used table views and implemented a third party library to enable swipe actions on the cells. While there may be advanced functionality baked into this library, I found out today that swipe actions are actually built into UIKit.
Both implementations get a bit ugly, but it’s nicer to not worry about needing an extra dependency if you dont have to!
Implementation
Here’s a rough overview of how to do it using the built in method:
func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {
let firstAction = UIContextualAction(style: .normal, title: "Delete or Something") {
(action, // 1
view, // 2
handler // 3
) in
// do stuff like deleting the data and then the row here
print("BELETED.")
handler(false)
}
firstAction.backgroundColor = .red
//and again easier to read without all the comments
let secondAction = UIContextualAction(style: .normal, title: "1up") { (action, view, handler) in
//gamify your app here
print("You scored a 1-up")
handler(true)
}
secondAction.backgroundColor = UIColor(red: 0.1, green: 0.8, blue: 0.3, alpha: 1.0)
return UISwipeActionsConfiguration(actions: [firstAction, secondAction])
}
- a reference to the action (
firstAction
in this case)
- source view in which action was displayed (apparently a
UIButtonLabel
– not sure what it is (other than obviously a button variant) or how it’s helpful)
- The handler block for you to execute after you have performed the action. This block has no return value and takes the following parameter:
- actionPerformed:
- A Boolean value indicating whether you performed the action. Specify true if you performed the action or false if you were unable to perform the action for some reason.
- I don’t totally understand the handler. You’re supposed to pass it
true
if whatever your operation is was a success, or false
if it failed… but it seems to behave the same either way
Here’s how it looks in the end:
Pull to refresh
Unlike swiping a table cell, I’ve never implemented a pull to refresh function in any of my apps. Partly because it looked hard, and partly because I didn’t have any apps that needed it. I also was under the impressio. that it required a third party library, and DID once upon a time, but now it’s available as part of the default UIKit. And it’s easy to use!
Implementation
It’s actually very easy.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
configureRefresh() //4
}
func configureRefresh() {
tableView.refreshControl = UIRefreshControl() //1
tableView.refreshControl?.addTarget(self, action: #selector(refreshMahDatas), for: .valueChanged) //2
}
@objc func refreshMahDatas() { //3
// simulating a network delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.dataArray = self.dataArray.map { $0 + 3 }
self.tableView.refreshControl?.endRefreshing()
self.tableView.reloadData()
}
}
- Initialize the
UIRefreshControl
on your tableview
- Add a target your custom update method
- Implement your custom update method
- It’s important that you run
endRefreshing()
here so the animation will stop
- you may safely omit the network delay simulation…
- And, be better than me and actually remember to call your configuration before you build it and wonder why it’s not working.
Here’s how it looks in the end:
Further Analysis
If you’d like a copy of the demo project, wander over here and check it out.
Swipe Actions
In my Poopmaster and RePNCalc apps, I had used table views and implemented a third party library to enable swipe actions on the cells. While there may be advanced functionality baked into this library, I found out today that swipe actions are actually built into UIKit.
Both implementations get a bit ugly, but it’s nicer to not worry about needing an extra dependency if you dont have to!
Implementation
Here’s a rough overview of how to do it using the built in method:
func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {
let firstAction = UIContextualAction(style: .normal, title: "Delete or Something") {
(action, // 1
view, // 2
handler // 3
) in
// do stuff like deleting the data and then the row here
print("BELETED.")
handler(false)
}
firstAction.backgroundColor = .red
//and again easier to read without all the comments
let secondAction = UIContextualAction(style: .normal, title: "1up") { (action, view, handler) in
//gamify your app here
print("You scored a 1-up")
handler(true)
}
secondAction.backgroundColor = UIColor(red: 0.1, green: 0.8, blue: 0.3, alpha: 1.0)
return UISwipeActionsConfiguration(actions: [firstAction, secondAction])
}
- a reference to the action (
firstAction
in this case) - source view in which action was displayed (apparently a
UIButtonLabel
– not sure what it is (other than obviously a button variant) or how it’s helpful) - The handler block for you to execute after you have performed the action. This block has no return value and takes the following parameter:
- actionPerformed:
- A Boolean value indicating whether you performed the action. Specify true if you performed the action or false if you were unable to perform the action for some reason.
- I don’t totally understand the handler. You’re supposed to pass it
true
if whatever your operation is was a success, orfalse
if it failed… but it seems to behave the same either way
- actionPerformed:
Here’s how it looks in the end:
Pull to refresh
Unlike swiping a table cell, I’ve never implemented a pull to refresh function in any of my apps. Partly because it looked hard, and partly because I didn’t have any apps that needed it. I also was under the impressio. that it required a third party library, and DID once upon a time, but now it’s available as part of the default UIKit. And it’s easy to use!
Implementation
It’s actually very easy.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
configureRefresh() //4
}
func configureRefresh() {
tableView.refreshControl = UIRefreshControl() //1
tableView.refreshControl?.addTarget(self, action: #selector(refreshMahDatas), for: .valueChanged) //2
}
@objc func refreshMahDatas() { //3
// simulating a network delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.dataArray = self.dataArray.map { $0 + 3 }
self.tableView.refreshControl?.endRefreshing()
self.tableView.reloadData()
}
}
- Initialize the
UIRefreshControl
on your tableview - Add a target your custom update method
- Implement your custom update method
- It’s important that you run
endRefreshing()
here so the animation will stop - you may safely omit the network delay simulation…
- It’s important that you run
- And, be better than me and actually remember to call your configuration before you build it and wonder why it’s not working.
Here’s how it looks in the end:
Further Analysis
If you’d like a copy of the demo project, wander over here and check it out.