I'm building a UIPanGestureRecognizer so I can move nodes in 3D space. 
Currently, I have something that works, but only when the camera is exactly perpendicular to the plane, my UIPanGestureRecognizer looks like this:
@objc func handlePan(_ sender:UIPanGestureRecognizer) {
  let projectedOrigin = self.sceneView!.projectPoint(SCNVector3Zero)
  let viewCenter = CGPoint(
    x: self.view!.bounds.midX,
    y: self.view!.bounds.midY
  )
  let touchlocation = sender.translation(in: self.view!)
  let moveLoc = CGPoint(
    x: CGFloat(touchlocation.x + viewCenter.x),
    y: CGFloat(touchlocation.y + viewCenter.y)
  )
  let touchVector = SCNVector3(x: Float(moveLoc.x), y: Float(moveLoc.y), z: Float(projectedOrigin.z))
  let worldPoint = self.sceneView!.unprojectPoint(touchVector)
  let loc = SCNVector3( x: worldPoint.x, y: 0, z: worldPoint.z )
  worldHandle?.position = loc
}
The problem happens when the camera is rotated, and the coordinates are effected by the perspective change. Here is you can see the touch position drifting:
Related SO post for which I used to get to this position: How to use iOS (Swift) SceneKit SCNSceneRenderer unprojectPoint properly
It referenced these great slides: http://www.terathon.com/gdc07_lengyel.pdf

