Start a new topic

iOS JavaScript API UI Background Thread crash

Hello,

I'm working on an iOS application and using the JavaScript API. I created the ViewController based on the example project, but my app crashes. Could you help to determinate what is wrong?

The crash log is the following:

  

2019-06-11 10:21:20.391695+0200 stepcounter[3088:873342] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2019-06-11 10:21:20.395836+0200 stepcounter[3088:873342] [MC] Reading from public effective user settings.
Unable to start WTArchitectView.

Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 3088, TID: 874018, Thread name: com.apple.CoreMotion.MotionThread, Queue name: com.apple.root.default-qos.overcommit, QoS: 0
Backtrace:
4   libobjc.A.dylib                     0x0000000239a436f4 <redacted> + 56
5   CoreMotion                          0x000000024018d638 CoreMotion + 292408
6   CoreMotion                          0x000000024018db68 CoreMotion + 293736
7   CoreMotion                          0x000000024018da78 CoreMotion + 293496
8   CoreMotion                          0x00000002401bb8a8 CoreMotion + 481448
9   CoreMotion                          0x00000002401bb8ec CoreMotion + 481516
10  CoreFoundation                      0x000000023a7cf78c <redacted> + 28
11  CoreFoundation                      0x000000023a7cf074 <redacted> + 276
12  CoreFoundation                      0x000000023a7ca368 <redacted> + 2276
13  CoreFoundation                      0x000000023a7c9764 CFRunLoopRunSpecific + 452
14  CoreFoundation                      0x000000023a7ca498 CFRunLoopRun + 84
15  CoreMotion                          0x00000002401bb280 CoreMotion + 479872
16  libsystem_pthread.dylib             0x000000023a449920 <redacted> + 132
17  libsystem_pthread.dylib             0x000000023a44987c _pthread_start + 48
18  libsystem_pthread.dylib             0x000000023a451dcc thread_start + 4
2019-06-11 10:21:24.325522+0200 stepcounter[3088:874018] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 3088, TID: 874018, Thread name: com.apple.CoreMotion.MotionThread, Queue name: com.apple.root.default-qos.overcommit, QoS: 0
Backtrace:
4   libobjc.A.dylib                     0x0000000239a436f4 <redacted> + 56
5   CoreMotion                          0x000000024018d638 CoreMotion + 292408
6   CoreMotion                          0x000000024018db68 CoreMotion + 293736
7   CoreMotion                          0x000000024018da78 CoreMotion + 293496
8   CoreMotion                          0x00000002401bb8a8 CoreMotion + 481448
9   CoreMotion                          0x00000002401bb8ec CoreMotion + 481516
10  CoreFoundation                      0x000000023a7cf78c <redacted> + 28
11  CoreFoundation                      0x000000023a7cf074 <redacted> + 276
12  CoreFoundation                      0x000000023a7ca368 <redacted> + 2276
13  CoreFoundation                      0x000000023a7c9764 CFRunLoopRunSpecific + 452
14  CoreFoundation                      0x000000023a7ca498 CFRunLoopRun + 84
15  CoreMotion                          0x00000002401bb280 CoreMotion + 479872
16  libsystem_pthread.dylib             0x000000023a449920 <redacted> + 132
17  libsystem_pthread.dylib             0x000000023a44987c _pthread_start + 48
18  libsystem_pthread.dylib             0x000000023a451dcc thread_start + 4
2019-06-11 10:21:35.220450+0200 stepcounter[3088:873875] void SendDelegateMessage(NSInvocation *): delegate (webView:didFinishLoadForFrame:) failed to return after waiting 10.000000 seconds. main run loop mode: kCFRunLoopDefaultMode
2019-06-11 10:21:35.225695+0200 stepcounter[3088:873342] Received memory pressure event 2 vm pressure 0

  

The ViewController is the following:

 

import UIKit

class TreasureHuntViewController: BaseViewController {
    
    @IBOutlet weak var architectView: WTArchitectView!
    
    private var architectWorldNavigation: WTNavigation?
    private let locationManager = CLLocationManager()
    private var poiGroups = [PoiGroup]()
    private var allPois = [Poi]()
    private var isPoisLoaded = false
    private var selectedMarkerLocation: CLLocation?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setup()
        fetchPoiGroups()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        startArchitectViewRendering()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        stopArchitectViewRendering()
    }
    
    @IBAction func didTouchFilterButton(_ sender: Any) {
        removeMarkers()
    }
    
}

extension TreasureHuntViewController: WTArchitectViewDelegate {
    
    func architectView(_ architectView: WTArchitectView, didFailToLoadArchitectWorldNavigation navigation: WTNavigation, withError error: Error) {
        print("Architect World from URL \(navigation.originalURL.absoluteString) could not be loaded. Reason: \(error.localizedDescription)");
    }
    
    func architectView(_ architectView: WTArchitectView, receivedJSONObject jsonObject: [AnyHashable : Any]) {
        if jsonObject.capacity > 0 {
            guard let latitude = jsonObject[Constants.Wikitude.PoiJsonKeys.ATTR_LATITUDE] as? Double,
                let longitude = jsonObject[Constants.Wikitude.PoiJsonKeys.ATTR_LONGITUDE] as? Double,
                let _ = jsonObject[Constants.Wikitude.PoiJsonKeys.ATTR_ALTITUDE] as? Double else { return }
            
            selectedMarkerLocation = CLLocation(latitude: latitude, longitude: longitude)
        }
    }
    
    func architectViewNeedsDeviceSensorCalibration(_ architectView: WTArchitectView) {
    }
    
}

extension TreasureHuntViewController: CLLocationManagerDelegate {
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        /*if let firstLocation = locations.first {
            let coordinate = firstLocation.coordinate
            architectView.injectLocation(withLatitude: coordinate.latitude,
                                         longitude: coordinate.longitude,
                                         altitude: firstLocation.altitude,
                                         accuracy: kCLLocationAccuracyBestForNavigation)
        }*/
        
        if allPois.count > 0 {
            if !isPoisLoaded {
                guard let poiJsonData = try? JSONSerialization.data(withJSONObject: Poi.convertPoisToJsonArray(allPois), options: []) else {
                    return
                }
                
                if let poiJson = String(data: poiJsonData, encoding: String.Encoding.utf8) {
                    print("World.loadPoisFromJsonData(" + poiJson + ")")
                    architectView.callJavaScript("World.loadPoisFromJsonData(" + poiJson + ")")
                    isPoisLoaded = true
                }
            }
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
        print(newHeading.magneticHeading)
    }
    
}

private extension TreasureHuntViewController {
    
    func setup() {
        navigationItem.title = Stack.treasureHunt.title()
        addMenuButtonToNavigationBar()
        addInfoButtonToNavigationBar()
        addOpenMenuGesture(to: view)
        addSeparatorViews()
        
        // Wikitude setup
        do {
            try WTArchitectView.isDeviceSupporting(.geo)
            architectView.setLicenseKey(Constants.Wikitude.licenseKey)
            architectView.delegate = self
            architectView.requiredFeatures = .geo
            
            if let architectWorldUrl = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "ARTreasureHunt") {
                architectWorldNavigation = architectView.loadArchitectWorld(from: architectWorldUrl)
            }
            
            NotificationCenter.default.addObserver(self, selector: #selector(didReceiveApplicationWillResignActiveNotification), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(didReceiveApplicationDidBecomeActiveNotification), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
            
            // Location setup
            if CLLocationManager.locationServicesEnabled() {
                locationManager.delegate = self
                locationManager.desiredAccuracy = kCLLocationAccuracyBest
                locationManager.distanceFilter = kCLLocationAccuracyBest
                locationManager.startUpdatingLocation()
                locationManager.startUpdatingHeading()
            }
        } catch {
            print(error)
        }
    }
    
    @objc func didReceiveApplicationWillResignActiveNotification() {
        DispatchQueue.main.async {
            if self.architectWorldNavigation?.wasInterrupted ?? true {
                self.architectView.reloadArchitectWorld()
            }
        }
        
        self.startArchitectViewRendering()
    }
    
    @objc func didReceiveApplicationDidBecomeActiveNotification() {
        self.stopArchitectViewRendering()
    }
    
    func startArchitectViewRendering() {
        DispatchQueue.main.async {
            if !self.architectView.isRunning {
                self.architectView.start({ configuration in
                    configuration.captureDevicePosition = .back
                    configuration.captureDeviceResolution = .AUTO
                }) { isRunning, error in
                    print("Unable to start WTArchitectView.")
                }
            }
        }
    }
    
    func stopArchitectViewRendering() {
        DispatchQueue.main.async {
            if (self.architectView.isRunning) {
                self.architectView.stop()
            }
        }
    }
    
    func fetchPoiGroups() {
        FirebaseManager.shared.getPoiGroups { [weak self] poiGroups in
            guard let wSelf = self else { return }
            
            wSelf.poiGroups = poiGroups
            
            poiGroups.forEach({ poiGroup in
                poiGroup.groupPois.forEach({ poi in
                    var poiCopy = poi.copy()
                    poiCopy.colorCode = poiGroup.groupColor
                    wSelf.allPois.append(poiCopy)
                })
            })
        }
    }
    
    func removeMarkers() {
        self.architectView.callJavaScript("World.removePois()")
    }
    
    func degreesToRadians(degrees: Double) -> Double {
        return degrees * .pi / 180.0
    }
    
    func radiansToDegrees(radians: Double) -> Double {
        return radians * 180.0 / .pi
    }
    
    func getBearingBetweenTwoPoints(point1: CLLocation, point2: CLLocation) -> Double {
        
        let lat1 = degreesToRadians(degrees: point1.coordinate.latitude)
        let lon1 = degreesToRadians(degrees: point1.coordinate.longitude)
        
        let lat2 = degreesToRadians(degrees: point2.coordinate.latitude)
        let lon2 = degreesToRadians(degrees: point2.coordinate.longitude)
        
        let dLon = lon2 - lon1
        
        let y = sin(dLon) * cos(lat2)
        let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
        let radiansBearing = atan2(y, x)
        
        return radiansToDegrees(radians: radiansBearing)
    }
    
}


I look forward to your early reply.

1 Comment

Hi,


Could you please provide the following details:


- Which version of the SDK are you using?
- What device does this happen with - is the crash device specific
- Is this happening with the sample app or in your own app? If it happens with your own app, does the sample app work on your device and did you make sure to initalize the ArchitectView as indicated in the documentation and handled in sample app?


If the issue persists, please send a complete demo project (ideally only consisting the necessary code to reproduce the crash) so we can investigate.


Thx and greetings

Nicola


Login or Signup to post a comment