iosswift3dtouchios-extensionspeek-pop

Peek & pop does not trigger only on the last cell


I have a ProfileVC that contain a list. I can click on any of the row cell will show peek and pop feature.

ProfileVC.swift

I added the extention

extension ProfileViewController : UIViewControllerPreviewingDelegate {
    
    func detailViewController(for indexPath: IndexPath) -> ProfileDetailViewController {
        guard let vc = storyboard?.instantiateViewController(withIdentifier: "ProfileDetailViewController") as? ProfileDetailViewController else {
            fatalError("Couldn't load detail view controller")
        }
        
        let cell = profileTableView.cellForRow(at: indexPath) as! ProfileTableViewCell
        
        // Pass over a reference to the next VC
        vc.title   = cell.profileName?.text
        vc.cpe     = loginAccount.cpe
        vc.profile = loginAccount.cpeProfiles[indexPath.row - 1]
        
        consoleLog(indexPath.row - 1)
        
        //print("3D Touch Detected !!!",vc)
        
        return vc
    }
    
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        if let indexPath = profileTableView.indexPathForRow(at: location) {
            
            // Enable blurring of other UI elements, and a zoom in animation while peeking.
            previewingContext.sourceRect = profileTableView.rectForRow(at: indexPath)
            
            return detailViewController(for: indexPath)
        }
        
        return nil
    }
    
    //ViewControllerToCommit
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        
        // Push the configured view controller onto the navigation stack.
        navigationController?.pushViewController(viewControllerToCommit, animated: true)
    }
    
}

Then, in the same file ProfileVC.swift in viewDidLoad() I registered it

if (self.traitCollection.forceTouchCapability == .available){
    print("-------->", "Force Touch is Available")
    registerForPreviewing(with: self, sourceView: view)
}
else{
    print("-------->", "Force Touch is NOT Available")
}

Result

I have no idea why I can not click on the 4th cell.

The last cell of the row does not trigger Peek & Pop.

How would one go about and debug this further?


Solution

  • You are registering your view controller's root view as the source view for the peek context. As a result, the CGPoint that is passed to previewingContext(_ viewControllerForLocation:)` is in the coordinate space of that view.

    When you try and retrieve the corresponding row from your table view the point will actually be offset from the corresponding point in the table view's frame based on the relative position of the table view in the root view.

    This offset means that a corresponding row can’t be retrieved for the last row in the table; indexPathForRow(at:) returns nil and your function returns without doing anything.

    You might also find that if you force touch towards the bottom of a cell you actually get a peek for the next row.

    You could translate the CGPoint into the table view’s frame, but it is simpler to just specify your tableview as the source view when you register for previewing:

    if (self.traitCollection.forceTouchCapability == .available){
        print("-------->", "Force Touch is Available")
        registerForPreviewing(with: self, sourceView: self.profileTableView)
    }
    else{
        print("-------->", "Force Touch is NOT Available")
    }