Is it possible to combine a peek and pop with a popover in iOS?
I want to use peek and pop with iPhones that support 3D Touch and at the same time a popover on iPads.
When I try to combine it in storyboard I get the error "Couldn't compile connection".
I have found the answer by myself.
The problem is, that the anchor point of the PopOver points to the prototype cell, which is dynamically created, so the system is not sure which cell is the anchor.
So the solution to this is the following:
UITableViewDataSource
(which in my case is the view controller) and add the following to your cellForRowAt()
using the cell as source view:func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCellIdentifier", for: indexPath) as! MyTableViewCell
let item = items[indexPath.row]
// Pass the item here...
registerForPreviewing(with: self, sourceView: cell) // <== Add this
return cell
}
UIViewControllerPreviewingDelegate
like this:extension ListeningVC: UIViewControllerPreviewingDelegate {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = tableView.indexPathForRow(at: location) else {
return nil
}
// get the item you want to pass using the index path
let item = items[indexPath.row]
// get the destination view controller
let destination = UIStoryboard(name: "...", bundle: nil).instantiateInitialViewController()
// Pass the item here...
return destination // return the destination view controller
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
// either present the view controller or add it to your navigation controller here
present(viewControllerToCommit, animated: true)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "mySegueIdentifier":
guard let cell = sender as? MyTableViewCell else { return }
guard let indexPath = tableView.indexPath(for: cell) else { return }
let item = items[indexPath.row]
let destination = segue.destination
// Pass the item here...
if let popOver = segue.destination.popoverPresentationController {
// set the cell as source view
let origin = CGPoint(x: 100, y: cell.frame.origin.y)
let size = CGSize(width: 200, height: cell.frame.height)
popOver.sourceView = tableView
popOver.sourceRect = CGRect(origin: origin, size: size)
}
default:
break
}
}