Goal
I'm trying to add the peek and pop feature to my table row
Usually, I am doing that using a simple cell extension:
class ForceTouchCell: UITableViewCell {
var previewingContext: UIViewControllerPreviewing?
func registerPreview(on controller: UIViewController, with delegate: UIViewControllerPreviewingDelegate) {
self.previewingContext = controller.registerForPreviewing(with: delegate, sourceView: self)
}
func unregisterPreview(on controller: UIViewController) {
guard let previewingContext = previewingContext else {
return
}
controller.unregisterForPreviewing(withContext: previewingContext)
self.previewingContext = nil
}
}
Then on the controller:
class MyController: UIViewController, UITableViewDelegate {
var tableView: UITableView!
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
guard traitCollection.forceTouchCapability != previousTraitCollection?.forceTouchCapability else {
return
}
let visibleCells = tableView.visibleCells
.compactMap { $0 as? ForceTouchCell }
if traitCollection.forceTouchCapability == .available {
visibleCells.forEach {
$0.registerPreview(on: self, with: self)
}
} else {
visibleCells.forEach {
$0.unregisterPreview(on: self)
}
}
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let forceTouchCell = cell as? ForceTouchCell {
if self.traitCollection.forceTouchCapability == .available {
forceTouchCell.registerPreview(on: self, with: self)
}
}
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
if let forceTouchCell = cell as? ForceTouchCell {
forceTouchCell.unregisterPreview(on: self)
}
}
}
extension MyConroller: UIViewControllerPreviewingDelegate {
func previewingContext(
_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint
) -> UIViewController? {
guard
let cell = (previewingContext.sourceView as? ForceTouchCell),
let indexPath = tableView.indexPath(for: cell)
else {
return nil
}
// use the indexPath/cell to create preview controller
}
The nice thing about this solution is the fact that it can be easily shared across controllers, e.g. using protocols with default implementations.
You are not getting the cell from the tableview. So the steps are as follows:
indexPath
using the location point fromUIViewControllerPreviewingDelegate
method.indexPath
to get cell from thetableView
.previewingContext
.Code Below:
In viewDidLoad
In Extension: