Struggles with GeoLocation

Code:

function getGeoInfo() {
  GeoLocation.onChanged = function(location) {
    console.log("Continuous: " + JSON.stringify(location));
    userLatitude.value = location.latitude;
    userLongitude.value = location.longitude;

    if(location.accuracy <= 10) {
      stopGeoListening();
    }
  };

  GeoLocation.onError = function(e) {
    console.log("GeoLocation Error: " + JSON.stringify(e));
  };

  startGeoListening();
}

function startGeoListening() {
  console.log("start listening...");

  GeoLocation.startListening(5000, 10);
}

function stopGeoListening() {
  console.log("stop listening...");
  GeoLocation.stopListening();
}

function updateGeo() {
  stopGeoListening();

  console.log("Attempting to get location");
  GeoLocation.getLocation().then(function(location) {
    console.log("Manual: " + JSON.stringify(location));
    userLatitude.value = location.latitude;
    userLongitude.value = location.longitude;

    if(location.accuracy > 10) {
      startGeoListening();
    }
  }).catch(function(e) {
    console.log(JSON.stringify(e));
  });
}

Problem:

I call getGeoinfo() upon app loading which starts listening for location changes every 5 seconds. It will stop listening once it finds something within accuracy of 10 meters.

I call updateGeo() based on a button click to Refine when necessary.

About every 2nd, 3rd or 4th time I call updateGeo, the app crashes on iOS with libc++abi.dylib: terminating with uncaught exception of type uThrowable: Uno.Exception.

My initial though was that it is conflicting with the listener, so I added the stopGeoListening() call before I call GeoLocation.getLocation() but that didn’t help at all.

Any thoughts on what I am doing wrong, or how I can trap the exception and find out what is really happening? I’m not a native iOS developer and trying to make use of the Fuse libraries as much as possible.

So I’ve actually narrowed this down to the MapView I think… when I comment it out, I don’t ever seem to run into the exception.

<ClientPanel ux:Name="mapPanel" Margin="0,25,0,50">
  <NativeViewHost>
    <MapView Latitude="{userLatitude}" Longitude="{userLongitude}" Zoom="16"
             AllowRotate="false" AllowTilt="false"
             ShowMyLocation="true" ShowMyLocationButton="true">
    </MapView>
  </NativeViewHost>
</ClientPanel>

It works fine initially, shows my location within the accuracy. But then when using GeoLocation.getLocation(), it seems the map is throwing the exception, not the GeoLocation class.

I also run into this with the MapView

Unable to simultaneously satisfy constraints.
	Probably at least one of the constraints in the following list is one you don't want. 
	Try this: 
		(1) look at each constraint and try to figure out which you don't expect; 
		(2) find the code that added the unwanted constraint or constraints and fix it. 
	(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x141c686e0 h=-&- v=-&- MKMapView:0x140a89820.height == UIView:0x140a89420.height>",
    "<NSLayoutConstraint:0x140869e60 UILayoutGuide:0x140c33050'Edge Insets'.top == MKMapView:0x140a89820.top + 20>",
    "<NSLayoutConstraint:0x14087a260 UILayoutGuide:0x140c33050'Edge Insets'.bottom == MKMapView:0x140a89820.bottom>",
    "<NSLayoutConstraint:0x141c68640 'UIView-Encapsulated-Layout-Height' V:[UIView:0x140a89420(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x14087a260 UILayoutGuide:0x140c33050'Edge Insets'.bottom == MKMapView:0x140a89820.bottom>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful

It looks like this may be iOS specific, but I have no idea how to troubleshoot. Does it have to do with the AllowRotate, AllowTilt, etc? Maybe some of them conflict?

Just for fun, what happens if you initialize userLatitude and userLongitude with some values? The Latitude/Longitude fields of the MapView expect some actual values to init and this might be the problem…

I have defaults already defined in the Observables. What I am finding is that using a combination of a listener AND manually calling GeoLocation.getLocation() is causing issues with the map. I think at some point there can be race issues or a conflict. I tried adding some variables to prevent things from happening if the other is “in progress” but because of the promises, it’s not full proof.

The only thing that’s been working for me at the moment without crashing the app (via MapView) is to only do GeoLocation.getLocation() based on a button I have on my map UI. I run it on app startup, then allow the user to control the refinement. Not ideal, but it doesn’t crash anymore.

It might be the observable lat/long pushing a new value before the map is fully initialized. I’ll investigate

I guess it’s possible, but I can see the map, rendered fine, showing my location. I then call getLocation() again via a button click and then it’ll crash on me. So it’s possible changing the lat/long via Observable is the culprit… even after the map is initialized.

I too have a libc++abi.dylib: terminating with uncaught exception of type uThrowable: Uno.Exception error when trying to get the location at the beginning of the app. It’s not always happening, I can’t reproduce the exact steps, but it crashes the app, specially when it was in background a lot of time and I call it back.

Update:

I think binding Latitude and Longitude to an Observable is part of my problem. I think the map is using GPS to update itself while I’m calling GeoLocation.getLocation() and it’s conflicting… perhaps?

I tested this by setting the maps lat/long to something specific and I don’t get the exception anymore. However, I need the map to be wherever the user is, so I need it to update frequently. ShowMyLocation icon updates as I move, but the map region does not.

Hey, so this appears to be a compound problem involving permissions(!). A significant update to both these APIs is being merged in currently that also fixes some issues with missing UI elements in the mapview. Thank you for being patient :slight_smile: Your code was used during the debugging of this.

Glad to be a bit of help!

Every bug reported is helpful :smiley:

Just ran into this myself: crashing on ios on every manual invocation of getLocation, on ios 10.
Glad you figured it out :wink:

Thanks! Will this thread be updated when a test build is available that includes the fix?

This is fixed in Fuse 0.25.5, which you can get from https://www.fusetools.com/downloads

Edit: The fix is only for Android

The Patch notes say “Fixed an issue where location fetch requests on Android would run on the wrong thread, sometimes resulting in a crash.” Which is great, however this problem wasn’t on Android (it may have been there too) but I am testing on iPhone. Was it identified for both platforms and fixed?

A quick test tells me it’s still broken on iOS.
Tip: sometimes logging the resulting object in a “then” right after receiving the location displays ok, but crashes when trying to return the value with an unspecified Uno exception.

Sorry, you’re right, the fix is only for Android. My mistake.

So sad to hear that this is not fixed yet :slightly_frowning_face:

I checked it out a bit further now. This is fixed for iOS too in Fuse 0.26, which is currently going through testing, and will be available soon.