Custom peek segue using Storyboard

Hello!


I've been trying to configure a custom peek segue using Storyboard. From my understanding I need to specify the ID of the segue to the peek view controller. I just have no idea how/where to define that segue: no matter what segue kind I select, the destination view controller always matches the one from the action segue (while the segue identifier is correctly set to the one I specified for the peek segue).


So far I have not written a single line of code that could potentially interfere with whatever happens under the hood.


Has anyone a working example of a custom peek segue configured with Storyboard?


Christian

Replies

you can test with a standard segue, yet declare it peek & poke.

You define 2 segues: SegueClick one from the cell protoype to a view1,

Another SeguePeek from the view Controller to another view view2


In the standard segue (SegueClick), you activate Peek & poke

And you give SeguePeek identifier in the Peek & Poke section of the standard segue SegueClick


You will have to implement UIViewControllerPreviewingDelegate in the viewController where the peek occurs. So, not everything can be done in IB.


Like this:



class Item2ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate  {

    @IBOutlet weak var tableForItem2: UITableView!

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if (segue.identifier == "SegueClick") {
            if let destController = segue.destination as? UIViewController {
            }
        }
    }

    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        guard let indexPath = tableForItem2.indexPathForRow(at: tableForItem2.convert(location, from: view)), let cell = tableForItem2.cellForRow(at: indexPath) else {
            return nil
        }

        let peekViewController = storyboard?.instantiateViewController(withIdentifier: "Peeking Cell") as! UIViewController
        peekViewController.preferredContentSize = CGSize(width: 0, height: 360)
        previewingContext.sourceRect = tableForItem2.convert(cell.frame, to: tableForItem2.superview!)
        return peekViewController
    }

    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        let navigationController = UINavigationController(rootViewController: viewControllerToCommit)
        show(navigationController, sender: self
    }

}


Tested : works in simulator (if the Mac has a trackpad)


If you want a custom one, you have to define your own segue subclass.


Detailed tutorial : h ttps://medium.com/@darjeelingsteve/supporting-3d-touch-peek-and-pop-ee80d2a4bd69

Hi, Claude31!


Thanks for you reply! I have a few questions regarding your code:

  1. What is the "SeguePeek" segue used for given you're instantiating the peek view controller manually?
  2. You did not register the UIViewControllerPreviewingDelegate. Was that an oversight or is it not necessary?
  3. If I enable the "Preview & Commit Segues" option, the UIViewControllerPreviewingDelegate methods never get called (regardless of whether I register the delegate or not). So I end up with the same behavior as before. Am I missing something?


Christian

Try to answer, but first : that does work on my XCode simulator on Mac with trackpad.


To test, I create 2 segues:

- one from the cellView (SegueClick) to show view1

- a second (SeguePeek), from the ViewController (control-drag from the leftmost icon at top of viewController, to a second view view2, when I longpress on the cell, for a peek.


The first segue is called directly when I click on the cell. No code to write, all handled by IB


The second segue is not triggered in the same way: it is available, but you must performSegue to activate it.

Hence, you have to write some code, and make the view controller conform to the delagete protocol UIViewControllerPreviewingDelegate.


So, now to your questions :

1. What is the "SeguePeek" segue used for given you're instantiating the peek view controller manually?

You're right, not needed. But the SeguePeek is needed, because used in the Peek & Pop Preview & Commit in IB


2. You did not register the UIViewControllerPreviewingDelegate. Was that an oversight or is it not necessary?

Not needed


3. If I enable the "Preview & Commit Segues" option, the UIViewControllerPreviewingDelegate methods never get called (regardless of whether I register the delegate or not). So I end up with the same behavior as before. Am I missing something?

You enable this option in the "normal" segue, when clicking in the cell : SegueClick


If you send your email, I can send you a complete test project.

I mistook on point 2 : yes, you need to register !


Sorry for the mistake.


    override func viewDidLoad() {
        super.viewDidLoad()
       
        // Do any additional setup after loading the view.
        if traitCollection.forceTouchCapability == .available {
            registerForPreviewing(with: self, sourceView: view)
        }
       
    }


Please tell if that works now.

Does it work now ?