Skip to content

[ARKit] GetGeolocationCallback NSError parameter should be an out parameter. #23051

Closed
@mandel-macaque

Description

@mandel-macaque

Apple platform

iOS

Framework version

net8.0-*

Affected platform version

.NET 9/main

Description

The GetGeolocationCallback is defined as following:

delegate void GetGeolocationCallback(CLLocationCoordinate2D coordinate, double altitude, NSError error);

But that is incorrect since that delegate comes from the objC definition:

- (void) getGeoLocationForPoint:([simd_float3](https://developer.apple.com/documentation/simd/simd_float3?language=objc)) position 
              completionHandler:(void (^)(CLLocationCoordinate2D coordinate, CLLocationDistance altitude, NSError * error)) completionHandler;

And as the Apple documentation states (https://developer.apple.com/documentation/arkit/arsession/getgeolocation(forpoint:completionhandler:)?language=objc) the error parameter is:

error
The reason, if conversion fails.

Both, the fact that the objC block declaration takes a pointer, and the documentation stating that it is actually set for an error, imply that the correct definition of the delegate should be:

delegate void GetGeolocationCallback(CLLocationCoordinate2D coordinate, double altitude, out NSError? error);

Unfortunately, updating the delegate to the correct signature will result in a bgen error BI1062 ( bgen: The member 'ARSession.GetGeoLocation' contains ref/out parameters and must not be decorated with [Async].) because the binding for 'getGeoLocationForPoint:completionHandler:' was declared as:

[iOS(14, 0)]
[Async(ResultTypeName = "GeoLocationForPoint")]
[MarshalDirective(NativePrefix = "xamarin_simd__", Library = "__Internal")]
[Export("getGeoLocationForPoint:completionHandler:")]
void GetGeoLocation(Vector3 position, GetGeolocationCallback completionHandler);

We need to create a deprecation for the Async method that does nothing and update the delegate declaration. This issue was found during the development of rgen because bgen generates:

[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
unsafe void Invoke (global::CoreLocation.CLLocationCoordinate2D coordinate, double altitude, NSError error)
{
	var error__handle__ = error.GetHandle ();
	invoker (BlockPointer, coordinate, altitude, error__handle__);
	GC.KeepAlive (error);
}

while rgen generates:

unsafe void Invoke (global::CoreLocation.CLLocationCoordinate2D coordinate, double altitude, global::Foundation.NSError error)
{
	if (error is null)
		global::ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (error));
	var error__handle__ = error.GetHandle ();
	invoker (BlockLiteral, coordinate, altitude, error__handle__);
	global::System.GC.KeepAlive (error);
}

RGen tries to be as compliant as possible with nullability, meaning that if a parameter is not set as a nullable out parameter, it will perform the null check and will throw the null argument exception.

Steps to Reproduce

Compile code.

Did you find any workaround?

No response

Relevant log output

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions