Search code examples
iosobjective-cuitableview3dtouch

3D Touch Peek and Pop from UITableViewCell how to hand over data to other UIViewController?


my app stores different attributes in Core Data objects. They are all shown in a UITableView, if you click a cell, a DetailView is shown. the usual stuff like in the Master-Detail-XCode-Template.

Now I want to implement 3D Touch with peek and pop. Like in the Mail app, 3D touch a cell, get preview, press deeper, pop in the detail.

I got this working so far, but I can t figure out how to pass the corresponding data in

- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location

and

- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit

to the other DetailViewController.

If you just click the cell (no 3D touch) I hand over the data in

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    [[segue destinationViewController] setDetailItem:object];

I am using a

id detailItem

in every ViewController and I set the corresponding object to it.

So I try to get something similar to work, so in my DetailViewController my "detailItem" needs the corresponding Core Data object from the selected (3D touched) cell.

Thanks for help !


Solution

  • Get the destination View controller from the storyboard using its storyboard ID and pass the objects that you are doing in prepareForSegue method.

    Below is the code that I use to pass the data. Its in Swift, it should be similar in objective C. Let me know if you want Objective C version.

    func previewingContext(previewingContext: UIViewControllerPreviewing,viewControllerForLocation location: CGPoint) -> UIViewController? method:
    
        // Obtain the index path and the cell that was pressed.
        guard let indexPath = tableView.indexPathForRowAtPoint(location),
                  cell = tableView.cellForRowAtIndexPath(indexPath) else { return nil }
    
        // Create a destination view controller and set its properties.
        guard let destinationViewController = storyboard?.instantiateViewControllerWithIdentifier("DestinationViewController") as? DestinationViewController else { return nil }
        let object = fetchedResultController.objectAtIndexPath(indexPath)
        destinationViewController.detailItem = object
    
        /*
            Set the height of the preview by setting the preferred content size of the destination view controller. Height: 0.0 to get default height
        */
        destinationViewController.preferredContentSize = CGSize(width: 0.0, height: 0.0)
    
        previewingContext.sourceRect = cell.frame
    
        return destinationViewController
    }