SOLUTION
Thanks to Carpsen90
You have to set the backgroundColor of that UIImageView to .clear, but it doesn't exist in the time of viewWillLayoutSubviews. It is created after you swipe.
A posible solution is to have a Timer:
var timerCellSwipeButtons: Timer?
Launched when the swipe is done:
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let editAction = UIContextualAction.init(style: .normal, title: nil) { [weak self] (action, view, completion) in
// editAction code
}
let deleteAction = UIContextualAction.init(style: .normal, title: nil) { [weak self] (action, view, completion) in
// deleteAction code
}
// Set the button's images
editAction.image = UIImage.init(named: "editIcon")
deleteAction.image = UIImage.init(named: "deleteIcon")
// You also must set the background color of the actions to .clear
editAction.backgroundColor = .clear
deleteAction.backgroundColor = .clear
// Launch the timer, that will run a function every 10 milliseconds
self.timerCellSwipeButtons = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(timerCellSwipeButtonsFunction), userInfo: nil, repeats: true)
// Return the actions
return UISwipeActionsConfiguration.init(actions: [deleteAction, editAction])
}
Now every 10 milliseconds (you can increase the frequency if you want), this function checks the tableView subviews looking for all the UISwipeActionStandardButton and setting to .clear the backgroundColor of their UIView:
@objc func timerCellSwipeButtonsFunction() {
// Gets all the buttons, maybe we have more than one in a row
let buttons = tableView.allSubViews.filter { (view) -> Bool in
String(describing: type(of: view)) == "UISwipeActionStandardButton"
}
// Loops through all the buttons
for button in buttons {
if let view = button.subviews.first(where: { !($0 is UIImageView)})
{
// We are interested in the UIView that isn't a UIImageView
view.backgroundColor = .clear
}
}
// When finish, timer is invalidated because we don't need it anymore.
// A new one will be launched with every swipe
self.timerCellSwipeButtons?.invalidate()
}
To get all the subviews of a UIView, I used the function given by Carpsen90:
extension UIView {
var allSubViews : [UIView] {
var array = [self.subviews].flatMap {$0}
array.forEach { array.append(contentsOf: $0.allSubViews) }
return array
}
}
For safety reasons, you should also invalidate the timer in the viewWillDisappear method:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.timerCellSwipeButtons?.invalidate()
}
And this is the result:
But as you can see, when you have more than one action in the same side of the cell and you swipe completely, doesn't look very nice:
To avoid icons overlapping I put only one action in each side:
// Remember to launch the timer in both swipe functions, like in the example above
// Function to add actions to the leading side of the cell
tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
// Function to add actions to the trailing side of the cell
tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?