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.

  • detect when UIPopoverController has finished presented UIImageViewcontroller
  • How to get path to a subfolder in main bundle?
  • Parse/Parse.h file not found when Xcode Quits
  • Is there an issue with CGColorGetComponents?
  • Asynchronous downloading of images for UITableView with GCD
  • I need help getting a normal looking unicode down arrow in a UILabel like this ⬇
  • 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 !

    3 Solutions Collect From Internet About “3D Touch Peek and Pop from UITableViewCell how to hand over data to other UIViewController?”

    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
    }
    

    If you are using storyboard segues from the cell to the new view controller, the sender is the table view cell.

    So you could implement prepareForSegue: as such:

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    
        if ([sender isKindOfClass:[UITableViewCell class]]) {
    
            UITableViewCell *cell = sender;
            NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    
            id viewController = segue.destinationViewController;
    
            // Get your data object
            // Pass it to the new view controller
        }
    }
    

    Base on Dheeraj’s reply, adjust some code to rectify the wrong touch location of tableview cell. Assume we need pass the value named type to destination controller.

    - (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
    // check if we're not already displaying a preview controller
    if ([self.presentedViewController isKindOfClass:[DetailViewController class]]) {
        return nil;
    }
    
    CGPoint cellPostion = [self.tableview convertPoint:location fromView:self.view];
    NSIndexPath *path = [self.tableview indexPathForRowAtPoint:cellPostion];
    
    if (path) {
        UITableViewCell *cell = [self.tableview cellForRowAtIndexPath:path];
        type = [[self.data objectAtIndex:path.row] integerValue];
        // shallow press: return the preview controller here (peek)
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        DetailViewController *previewController = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
        previewController.type = type;
        previewingContext.sourceRect = [self.view convertRect:cell.frame fromView:self.tableview];
        return previewController;
    }
    return nil;
    

    }