iOS AGSLocator object doesn't support OutSpatialReference?

3084
4
11-03-2011 12:35 PM
HasheenDeBerry
New Contributor III
Hello All,

I am VERY new to iOS development.  I've spent the last few years programming using the Silverlight API...

...Anyways I think I may have stumbled on a bug.  I was following the example in the ArcGIS iOS API for geocoding and for some reason I cannot get the AGSLocator object to return my address candidates in the correct spatial reference.  If I specify web mercator (WKID: 102100) I get my candidates back off the coast of Africa (clearly in WGS-84).

I am using Xcode v4.2 and I am using the iOS API with Automated Reference Counting enabled.

here is some code from my AddressFinder.m file
- (IBAction)btnLocate_Click:(id)sender 
{
    //show progress indicator graphic
    self.progressIndicator.hidden = NO;
    
    //collect values from text fields
    self.address1 = self.txtAddress1.text;
    self.address2 = self.txtAddress2.text;
    self.addressCity = self.txtAddressCity.text;
    self.addressState = self.txtAddressState.text;
    self.addressZip = self.txtAddressZip.text;
    
    ...
    
    //package address input for geocoder
    self.addressFields = [[NSDictionary alloc]initWithObjectsAndKeys:self.address1, @"Street", self.addressCity, @"City", self.addressState, @"State", self.addressZip, @"ZIP", nil];
    
    //specify return fields for the address candidates coming back
    self.outFields = [NSArray arrayWithObjects: @"Score", @"Match_addr", @"StreetName", @"X", @"Y", nil];
    
    //disable UI input while search is in progress
    [self ToggleEnableAll:NO];
    self.btnLocate.enabled = NO;
    self.btnClear.enabled = NO;
    
    //fire up geocoder if applicable
    if(self.locationService == nil)
    {
        if(self.locatorRESTEndpoint != NULL && self.locatorRESTEndpoint != @"")
        {
            NSURL *locatorURL = [[NSURL alloc] initWithString:self.locatorRESTEndpoint];
            self.locationService = [[AGSLocator alloc]initWithURL:locatorURL];
        }
        else
        {
            //alert user that no REST endpoint was specified. bad news bears
            ...
            
            return;
        }
    }
    
    self.locationService.delegate = self; //AGSLocator object
    
    //hit geocode service and handle output in delegate functions below
    [self.locationService locationsForAddress:self.addressFields returnFields:self.outFields outSpatialReference:self.mapSpatialReference];

}

I output the value of 'self.mapSpatialReference.wkid' and I get 102100 as expected.  Here's my callback code

- (void)locator:(AGSLocator *)locator operation:(NSOperation*)op didFindLocationsForAddress:(NSArray *)candidates
{
    if(candidates.count == 0)
    {
        //alert user that no candidates came back
        ...
    }
    else
    {
        //restore UI 
        [self ToggleEnableAll:YES];
        self.btnLocate.enabled = YES;
        self.btnClear.enabled = YES;
        
        //call delegate so that subscribers can handle candidate data
        [self.delegate OnFoundCandidates:candidates];
    }
    
    //hide progress indicator
    self.progressIndicator.hidden = YES;
}


if more than zero candidates come back I handle them on my main view controller. Here is code from the delegate function

- (void) OnFoundCandidates : (NSArray *)candidates
{  
    //this is the callback for the geocoder's "found address candidate" delegate
    //here we'll be either putting a point on the map for the best candidate or
    //allowing the user to choose his/her intended candidate
    if(candidates.count == 1)
    {
        //put it on the map
        AGSAddressCandidate *soleCandidate = [candidates objectAtIndex:0];
        if(soleCandidate)
        {
            //initialise symbol and geometry
            AGSPoint *mapPoint = soleCandidate.location;
            AGSSimpleMarkerSymbol *sms =  [[AGSSimpleMarkerSymbol alloc]initWithColor:[UIColor blueColor]];
            
            //initialise graphic
            AGSGraphic *candidateGraphic = [[AGSGraphic alloc]initWithGeometry:mapPoint symbol:sms attributes:nil infoTemplateDelegate:nil];
            
            //transfer attributes from candidate to graphic for callout data display later
            [candidateGraphic.attributes addEntriesFromDictionary:soleCandidate.attributes];
            
            //close popover
            [self.testController dismissPopoverAnimated:YES];
            
            //add graphic to map
            [self.geocodeGraphicsLayer addGraphic:candidateGraphic];
            [self.geocodeGraphicsLayer dataChanged];
        }
    }
    else
    {
        AGSAddressCandidate *oneHundredPercentMatch;
        
        for(AGSAddressCandidate * candidate in candidates)
        {
            if([[candidate.attributes objectForKey:@"Score"] doubleValue] == 100.0f)
            {
                oneHundredPercentMatch = candidate;
                break;
            }
        }
        
        if(oneHundredPercentMatch != nil && oneHundredPercentMatch != NULL)
        {
            NSLog(@"100 percent match: %f, %f ::: %f, %f",oneHundredPercentMatch.location.x, oneHundredPercentMatch.location.y, [[oneHundredPercentMatch.attributes objectForKey:@"X"]doubleValue], [[oneHundredPercentMatch.attributes objectForKey:@"Y"]doubleValue]);
            //initialise symbol and geometry
            AGSPoint *mapPoint = oneHundredPercentMatch.location;
            AGSSimpleMarkerSymbol *sms = [[AGSSimpleMarkerSymbol alloc]initWithColor:[UIColor blueColor]];
            
            //intiialise graphic
            AGSGraphic *candidateGraphic = [[AGSGraphic alloc]initWithGeometry:mapPoint symbol:sms attributes:nil infoTemplateDelegate:nil];
            
            //transfer attributes from candidate to graphic for callout data display later
            [candidateGraphic.attributes addEntriesFromDictionary:oneHundredPercentMatch.attributes];
            
            //close popover
            [self.testController dismissPopoverAnimated:YES];
            
            //add graphic to map
            [self.geocodeGraphicsLayer addGraphic:candidateGraphic];
            [self.geocodeGraphicsLayer dataChanged];
        }
        else
        {
            ...
        }
    }
}

The geocode service i was using is http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Locators/ESRI_Geocode_USA/GeocodeServer.  when I use the service in a browser I get the expected results which leads me to believe that the AGSLocator object doesn't support outspatialreference.

Sorry for being so verbose.  I've been chasing my tail for a while and hope that someone can help.

Thanks in advance,
Hasheen
Reply
0 Kudos
4 Replies
HasheenDeBerry
New Contributor III
I've implemented a workaround that will call on a geometry service to reproject the point coming back from the geocoder if the basemap's spatial reference is not WGS-84.  I still welcome any suggestions as to what I might be missing.  Thanks for the help!

H
Reply
0 Kudos
NimeshJarecha
Esri Regular Contributor
If you use following service, then also see the same issue?

http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Locators/ESRI_Geocode_NA/GeocodeServer

Regards,
Nimesh
Reply
0 Kudos
HasheenDeBerry
New Contributor III
hi @Nimesh!

I plugged that service into my code and it seems to work.  I commented out the code that reprojects the points coming back from the geocoder and it seems to still work. 

Is there some way to detect whether a service supports an output spatial reference?

Thank you for your help!

Regards,
Hasheen
Reply
0 Kudos
NimeshJarecha
Esri Regular Contributor
Great!

The geocode service from ArcGIS Server v10 onwards supports out spatial reference. The other service should work too but seems to have some issue with it.

Regards,
Nimesh
Reply
0 Kudos