In swiftui ARKit application for putting selected image on floor i am getting the error Call to main actor-isolated static method 'loadMainScene()' in a synchronous nonisolated context at line self.mainScene = try! Experience.loadMainScene() . How to resolve abover error?
import Foundation
import RealityKit
import ARKit
class Coordinator {
var arView: ARView?
var mainScene: Experience.MainScene
var vm: FurnitureViewModel
init(vm: FurnitureViewModel) {
self.vm = vm
self.mainScene = try! Experience.loadMainScene()
}
@objc func tapped(_ recognizer: UITapGestureRecognizer) {
guard let arView = arView else {
return
}
let location = recognizer.location(in: arView)
let results = arView.raycast(from: location, allowing: .estimatedPlane, alignment: .horizontal)
if let result = results.first {
let anchor = AnchorEntity(raycastResult: result)
guard let entity = mainScene.findEntity(named: vm.selectedFurniture) else {
return
}
entity.position = SIMD3(0,0,0)
anchor.addChild(entity)
arView.scene.addAnchor(anchor)
}
}
}
// // Experience.swift // GENERATED CONTENT. DO NOT EDIT. //
import Foundation import RealityKit import simd import Combine
@available(iOS 13.0, macOS 10.15, *) public enum Experience {
public enum LoadRealityFileError: Error {
case fileNotFound(String)
}
@MainActor
private static var streams = [Combine.AnyCancellable]()
@MainActor
public static func loadMainScene() throws -> Experience.MainScene {
guard let realityFileURL = Foundation.Bundle(for: Experience.MainScene.self).url(forResource: "Experience", withExtension: "reality") else {
throw Experience.LoadRealityFileError.fileNotFound("Experience.reality")
}
let realityFileSceneURL = realityFileURL.appendingPathComponent("MainScene", isDirectory: false)
let anchorEntity = try Experience.MainScene.loadAnchor(contentsOf: realityFileSceneURL)
return createMainScene(from: anchorEntity)
}
@MainActor
public static func loadMainSceneAsync(completion: @escaping (Swift.Result<Experience.MainScene, Swift.Error>) -> Void) {
guard let realityFileURL = Foundation.Bundle(for: Experience.MainScene.self).url(forResource: "Experience", withExtension: "reality") else {
completion(.failure(Experience.LoadRealityFileError.fileNotFound("Experience.reality")))
return
}
var cancellable: Combine.AnyCancellable?
let realityFileSceneURL = realityFileURL.appendingPathComponent("MainScene", isDirectory: false)
let loadRequest = Experience.MainScene.loadAnchorAsync(contentsOf: realityFileSceneURL)
cancellable = loadRequest.sink(receiveCompletion: { loadCompletion in
if case let .failure(error) = loadCompletion {
completion(.failure(error))
}
streams.removeAll { $0 === cancellable }
}, receiveValue: { entity in
completion(.success(Experience.createMainScene(from: entity)))
})
cancellable?.store(in: &streams)
}
@MainActor
private static func createMainScene(from anchorEntity: RealityKit.AnchorEntity) -> Experience.MainScene {
let mainScene = Experience.MainScene()
mainScene.anchoring = anchorEntity.anchoring
mainScene.addChild(anchorEntity)
return mainScene
}
public class MainScene: RealityKit.Entity, RealityKit.HasAnchoring {
public var armoire: RealityKit.Entity? {
return self.findEntity(named: "armoire")
}
public var chair: RealityKit.Entity? {
return self.findEntity(named: "chair")
}
public var sofa: RealityKit.Entity? {
return self.findEntity(named: "sofa")
}
public var table: RealityKit.Entity? {
return self.findEntity(named: "table")
}
}
}
Any help would be appreciated.
Since the loadMainScene()
static function was marked with the @MainActor
annotation, which means this function will perform on the main thread. So, you also need to add @MainActor to your init function.
@MainActor
init(vm: FurnitureViewModel) {
...
}
Or provide a default value for mainScene
and perform a @MainActor task in the init function.
var mainScene: Experience.MainScene! //<- Default value here.
init(vm: FurnitureViewModel) {
...
Task { @MainActor in
self.mainScene = try! Experience.loadMainScene()
}
}