If I understand you correctly, I do this using a UIPanGestureRecognizer added to the ARSCNView.
In my case I want to check if pan was started on a given virtual object and keep track of which it was because I can have multiple, but if you have just one object you may not need the targetNode variable.
The 700 constant I use to divide I got it by trial and error to make the translation smoother, you may need to change it for your case.
Moving finger up, moves the object further away from camera and moving it down moves it nearer. Horizontal movement of fingers moves object left/right.
@objc func onTranslate(_ sender: UIPanGestureRecognizer) {
let position = sender.location(in: scnView)
let state = sender.state
if (state == .failed || state == .cancelled) {
return
}
if (state == .began) {
// Check pan began on a virtual object
if let objectNode = virtualObject(at: position).node {
targetNode = objectNode
latestTranslatePos = position
}
}
else if let _ = targetNode {
// Translate virtual object
let deltaX = Float(position.x - latestTranslatePos!.x)/700
let deltaY = Float(position.y - latestTranslatePos!.y)/700
targetNode!.localTranslate(by: SCNVector3Make(deltaX, 0.0, deltaY))
latestTranslatePos = position
if (state == .ended) {
targetNode = nil
}
}