Reputation: 51
I'm trying to use 3D Touch and everything is fine except in the function below I can't get the right value indexPath
with indexPathForRow(at: location)
when I'm scrolling. This function can't say if user scrolls the table or not and always set the first row that user can see in app as first one.
My code:
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = workoutTable?.indexPathForRow(at: location) else {return nil }
guard let cell = workoutTable?.cellForRow(at: indexPath) else {return nil }
guard let workoutDetailPeek = storyboard?.instantiateViewController(withIdentifier: "WorkoutDetailPeek") as? WorkoutDetailPeek else {print("else31"); return nil }
workoutDetailPeek.workoutId = "\(Int(workout[(indexPath as NSIndexPath).row].workoutId)!-2)"
workoutDetailPeek.preferredContentSize = CGSize(width: 400.0, height: 267.0)
previewingContext.sourceRect = cell.frame
return workoutDetailPeek
}
I been through different 3D Touch implementation, but this function seems to works fine for everyone except me.
Upvotes: 1
Views: 126
Reputation: 25
You need to convert into the tableView's coordinate system
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
// convert location to the tableView's coordinate system to get the right cell
let locationInTableViewCoordinate = view.convert(location, to: tableView)
guard let indexPath = tableView.indexPathForRow(at: locationInTableViewCoordinate), let cell = tableView.cellForRow(at: indexPath) else { return nil }
// for the blur you need to to the reverse, since the cell is expressed in the tableView's coordinate and the blur is in the view's
let frame = tableView.convert(cell.frame, to: view)
previewingContext.sourceRect = frame
// you should not guard the instantiation, this is a case where you want to fail early is something is wrong
let workoutDetailPeek = storyboard?.instantiateViewController(withIdentifier: "WorkoutDetailPeek") as! WorkoutDetailPeek
return workoutDetailPeek
}
Upvotes: 1
Reputation: 131503
In iOS each view has 2 coordinate systems, it's own, and it's superview's. A view's coordinate system almost always has 0,0 in the upper left of the view. That point is likely to be someplace other than 0,0 in it's superview's coordinate system.
When you get a point, you need to know who's coordinate system it's expressed in. There are various methods in UIView that let you convert points between coordinate systems.
In order for your code to work you need to know which view's coordinate system the point is expressed in. Since you're searching for a cell in a table view, using the table view's coordinate system would be a reasonable choice.
I haven't developed for 3D touch devices yet so I'm not familiar with the function you're using. Where does the point come from that you're passing into it, and in what coordinate system is it expressed?
Upvotes: 1