I'm using ARKit-CoreLocation library to present POI
s in AR
World, in iOS 14
. But the thing is, I am not able to use ARCL
's SceneLocationView
because it is SCNView
. So when I add it as a subview, it overlaps my ARView
contents and creates a new ARSession
, leaving my ARView
in the background.
Code:
extension RealityKitViewController {
typealias Context = UIViewControllerRepresentableContext<RealityKitViewControllerRepresentable>
}
class RealityKitViewController: UIViewController {
let sceneLocationView = SceneLocationView()
let arView = ARView(frame: .zero)
let context : Context
let pins: [Pin]
var currentLocation : CLLocation? {
return sceneLocationView.sceneLocationManager.currentLocation
}
init (_ context : Context, pins: [Pin]) {
self.context = context
self.pins = pins
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeArView()
{
// Start AR session
let session = arView.session
let config = ARWorldTrackingConfiguration()
config.planeDetection = [.horizontal, .vertical]
session.run(config)
// Add coaching overlay
let coachingOverlay = ARCoachingOverlayView()
coachingOverlay.session = session
coachingOverlay.goal = .horizontalPlane
coachingOverlay.delegate = context.coordinator
arView.addSubview(coachingOverlay)
arView.debugOptions = [.showFeaturePoints, .showAnchorOrigins, .showAnchorGeometry]
// Handle ARSession events via delegate
context.coordinator.view = arView
session.delegate = context.coordinator
}
override func viewDidLoad() {
super.viewDidLoad()
// probably problem here
sceneLocationView.frame = view.bounds
arView.frame = sceneLocationView.bounds
sceneLocationView.addSubview(arView)
view.addSubview(sceneLocationView)
addPins()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
sceneLocationView.frame = view.bounds
}
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() 0.2) {
super.viewWillAppear(animated)
self.sceneLocationView.run()
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneLocationView.pause()
}
func addPins() {
guard let currentLocation = currentLocation, currentLocation.horizontalAccuracy < 16 else {
return DispatchQueue.main.asyncAfter(deadline: .now() 0.5) { [weak self] in
self?.addPins()
}
}
self.pins.forEach { pin in
guard pin.isLocation else { return }
guard let location = pin.location else { return assertionFailure() }
guard let image = UIImage(named: pin.image) else { return assertionFailure() }
let node = LocationAnnotationNode(location : location, image: image)
node.scaleRelativeToDistance = true
sceneLocationView.addLocationNodeWithConfirmedLocation(locationNode: node)
}
}
}
// if you want to test it, you can try to place these pins to a location where you can easily get coordinates from Google Earth.
struct RealityKitViewControllerRepresentable : UIViewControllerRepresentable {
let pins = [Pin(image: "test", location: CLLocation(coordinate: CLLocationCoordinate2D(latitude: 0.03275742958, longitude: 0.32827424), altitude: 772.1489524841309), isLocation: true)]
@Binding var arActivate : Bool
func makeUIViewController(context: Context) -> RealityKitViewController {
let viewController = RealityKitViewController(context, pins: pins)
return viewController
}
func updateUIViewController(_ uiViewController: RealityKitViewController, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
}
class Coordinator: NSObject, ARSessionDelegate {
weak var view: ARView?
}
CodePudding user response:
I solved the problem: There's no solution.
Using SCNView
as a subview is a really horrible idea yet every answer I found says "no", it seems like this feature will remin unresolved until Apple
releases an integration or something for that.