Using TTMSFNCGeocodingItems

Hi

I am adapted a function you describe here
https://support.tmssoftware.com/t/geocoding-with-callback-not-processed-into-datamodule/14166/6

My function returns a TTMSFNCGeocodingItems variable.
Thus I created a variable and destroy it later following this way, is it correct ?

procedure TfMigration.Button27Click(Sender: TObject);
var
  coor: TTMSFNCMapsCoordinate;
  Infos: string;
  Georefs: TTMSFNCGeocodingItems;
   Succes : Boolean;

begin
    TRY

        TRY
            fPrincipal.FNCGeocoding.service := gsHere;
            fPrincipal.FNCGeocoding.APIKey := 'xxxxxx';
            Georefs := TTMSFNCGeocodingItems.Create(NIL);
            Georefs := FPrincipal.GetGeocoding('london', Succes, Infos);
            IF Succes THEN
                Edit1.Text := Georefs.Items[0].Address;
        EXCEPT
            ON E: System.SysUtils.Exception DO
            BEGIN
            END;
        END;    // Fin de EXCEPT
    FINALLY
        Georefs.Free;
    END;   // Fin de FINALLY
end;

regards

Hi,

You need to destroy the variable inside the callback or event, because the request is asynchronous:

Latitude := '';
    Longitude:= '';
    geocoder := TTMSFNCGeocoding.Create(ServerContainer); //<== ServerContainer = DataModule
    geocoder.Service := gsGoogle;
    geocoder.APIKey := 'zzzzzzz';
    // Check if CodePostal is ... a CodePOstal

    // Retrieve Lat, Long from ZIP code
    sTempAdr := CodePostal+',France';
    geocoder.GetGeocoding(sTempAdr,
        procedure(const ARequest: TTMSFNCGeocodingRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
        begin
             Longitude := ARequest.Items[0].Coordinate.longitude.ToString;
             Latitude  := ARequest.Items[0].Coordinate.Latitude.ToString;
             FreeAndNil(geocoder);
        end
    );
   ..

Thanks a lot

What you can do as well is converting the method into a synchronous implementation with the following code:

unit Unit10;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.TMSFNCCustomComponent, FMX.TMSFNCCloudBase, FMX.TMSFNCGeocoding, FMX.TMSFNCMapsCommonTypes,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm10 = class(TForm)
    TMSFNCGeocoding1: TTMSFNCGeocoding;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    FRequestResult: string;
    function GetGeocoding(AAddress: string): TTMSFNCMapsCoordinateRec;
    procedure DoRequestAddress(
      const ARequestResult: TTMSFNCCloudBaseRequestResult);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.fmx}

uses
  FMX.TMSFNCUtils;

procedure TForm10.Button1Click(Sender: TObject);
var
  c: TTMSFNCMapsCoordinateRec;
begin
  c := GetGeocoding('MyAddress');
end;

procedure TForm10.DoRequestAddress(const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  FRequestResult := ARequestResult.ResultString;
end;

function TForm10.GetGeocoding(AAddress: string): TTMSFNCMapsCoordinateRec;
var
  req: TTMSFNCGeocodingRequest;
  lon, lat: Double;
begin
  Result := DefaultCoordinate;

  TMSFNCGeocoding1.APIKey := '';
  TMSFNCGeocoding1.Service := gsHere;

  TMSFNCGeocoding1.Request.Clear;
  TMSFNCGeocoding1.Request.ClearHeaders;
  TMSFNCGeocoding1.Request.Name := 'GET GEOCODING';
  TMSFNCGeocoding1.Request.Method := TMSFNCGeocoding1.GeocodingInstance.GetRequestMethod;
  TMSFNCGeocoding1.Request.Host := TMSFNCGeocoding1.GeocodingInstance.GetHost;
  TMSFNCGeocoding1.Request.Path := TMSFNCGeocoding1.GeocodingInstance.GetPath(TTMSFNCUtils.URLEncode(AAddress));
  TMSFNCGeocoding1.Request.Query := TMSFNCGeocoding1.GeocodingInstance.GetQuery(TTMSFNCUtils.URLEncode(AAddress));
  TMSFNCGeocoding1.Request.PostData := TMSFNCGeocoding1.GeocodingInstance.GetPostData;

  TMSFNCGeocoding1.ExecuteRequest(DoRequestAddress, nil, False);
  if FRequestResult <> '' then
  begin
    req := TMSFNCGeocoding1.GeocodingRequests.Add;
    TMSFNCGeocoding1.GeocodingInstance.Parse(req, FRequestResult);
    lon := req.Items[0].Coordinate.longitude;
    lat := req.Items[0].Coordinate.Latitude;
    Result := CreateCoordinate(lat, lon);
  end;
end;


end.

Thanks a lot

This is the solution I flinally used. I found it in an other post.

Possible to add this info into the PDF ?
regards
olivier

Well, this is a solution, but not the ideal one, we'll probably add a synchronous function that does the same thing instead, so before we update the documentation we'll need more time to investigate a permanent & more elegant solution to retrieve the coordinates in a synchronous way.

Of course, That will be a major improvement (at least for me) ;)
regards

I second this, adding a synchronous method to do geocoding would be really useful.

In the latest version, there is a sync version added. Use GetGeocodingSync to retrieve the value without needing a callback.