2014-04-30 12 views
8

Ho tre campi di testo nella mia vista. 1. CAP, 2. Città e 3. Stato.Compilazione automatica città e stato dal codice di avviamento postale in iOS

Come compilare automaticamente il campo città e stato dal codice di avviamento postale in iOS?

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 
    NSString *currentString = [textField.text stringByReplacingCharactersInRange:range withString:string]; 
    int length = [currentString length]; 
    if(length > 5) 
    { 
     return NO; 
    } 
    if(length == 5) 
    { 
     [self getCityAndState]; 
    } 
    return YES; 
} 

- (void) getCityAndState 
{ 
    //How to use google (or any) api to autofill city and state in objective - c? 
} 
+0

Usa Goolge geocodifica API - [vedere questo] (https://developers.google.com/maps/documentation/geocoding/?csw=1) – Shruti

+0

controllare questo link http://stackoverflow.com/questions/4749706/lookup-city-and-state-by-zip-google-geocode-api – user2071152

risposta

10

Utilizzare la Google GeoCoding API per estrarre le informazioni, se si desidera inviare il codice di avviamento postale per ricevere altre informazioni, utilizzare questo:

NSString *strRequestParams = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=&components=postal_code:%@&sensor=false",zipCode]; 

strRequestParams = [strRequestParams stringByAddingPercentEscapesUsingEncoding:NSStringEncodingConversionExternalRepresentation]; 

NSURL *url = [NSURL URLWithString:strRequestParams]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 

[request setHTTPMethod:@"GET"]; 

NSError *error; 
NSURLResponse *response; 
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 
if (!response) { 
    // "Connection Error", "Failed to Connect to the Internet" 
} 

NSString *respString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] ; 
//NSLog(@"RECEIVED DATA : %@", respString); 

Se la variabile codice postale è 32000, si otterrà il risultato this JSON :

È possibile analizzare questo jSON per estrarre tutte le informazioni desiderate tra cui Paese, Città, longitudine, latitudine ecc

+2

@Khanwar Ali: Solo la ragione per cui non hai ancora accettato la tua risposta è shouldChangeCharactersInRange: (NSRange) il metodo range sta selezionando 4 caratteri dal campo zip invece di 5 dal campo di testo. Come? –

16

I cerca di evitare i servizi di Google perché tendono ad addebitare a un determinato livello di utilizzo. Ecco la soluzione utilizzando framework di Apple:

#import <CoreLocation/CoreLocation.h> 
#import <AddressBookUI/AddressBookUI.h> 

- (void)didEnterZip:(NSString*)zip 
{ 
    CLGeocoder* geoCoder = [[CLGeocoder alloc] init]; 
    [geoCoder geocodeAddressDictionary:@{(NSString*)kABPersonAddressZIPKey : zip} 
     completionHandler:^(NSArray *placemarks, NSError *error) { 
     if ([placemarks count] > 0) { 
      CLPlacemark* placemark = [placemarks objectAtIndex:0]; 

      NSString* city = placemark.addressDictionary[(NSString*)kABPersonAddressCityKey]; 
      NSString* state = placemark.addressDictionary[(NSString*)kABPersonAddressStateKey]; 
      NSString* country = placemark.addressDictionary[(NSString*)kABPersonAddressCountryCodeKey]; 

     } else { 
      // Lookup Failed 
     } 
    }]; 
} 
4

La risposta da A-r-studios è a posto, dal momento che non introduce una dipendenza sul servizio di Google.

Tuttavia, limiterò anche il codice paese basato sull'input dell'utente o solo negli Stati Uniti se ha senso. Non limitarlo dà risultati imprevedibili perché il geocoder può restituire più hit di diversi paesi.

#import <CoreLocation/CoreLocation.h> 
#import <AddressBookUI/AddressBookUI.h> 

- (void)didEnterZip:(NSString*)zip 
{ 
    CLGeocoder* geoCoder = [[CLGeocoder alloc] init]; 
    [geoCoder geocodeAddressDictionary:@{(NSString*)kABPersonAddressZIPKey : zip, 
      (NSString*)kABPersonAddressCountryCodeKey : @"US"} 
     completionHandler:^(NSArray *placemarks, NSError *error) { 
     if ([placemarks count] > 0) { 
      CLPlacemark* placemark = [placemarks objectAtIndex:0]; 

      NSString* city = placemark.addressDictionary[(NSString*)kABPersonAddressCityKey]; 
      NSString* state = placemark.addressDictionary[(NSString*)kABPersonAddressStateKey]; 
      NSString* country = placemark.addressDictionary[(NSString*)kABPersonAddressCountryCodeKey]; 

     } else { 
      // Lookup Failed 
     } 
    }]; 
} 
3

Mentre le risposte da alex_C e ar-studios funzionano bene, se non avete voglia di armeggiare con AddressBookUI o dizionari, si può semplicemente utilizzare il metodo geocodeAddressString:completionHandler: sulla geocoder passando il codice postale da solo che è sufficiente per la ricerca:

[[CLGeocoder new] geocodeAddressString:zip completionHandler:^(NSArray *placemarks, NSError *error) { 
    if (placemarks.count) { 
     CLPlacemark *placemark = placemarks.firstObject; 

     NSString *city = placemark.locality; 
     NSString *state = placemark.administrativeArea; 
    } 
}]; 

In Swift:

CLGeocoder().geocodeAddressString(zip) { (placemarks, error) in 
    if let result = placemarks?.first { 
     let city = result.locality 
     let state = result.administrativeArea 
    } 
} 
0
static func zipToAddress(zip: String, onSuccess: (String, String) -> Void, onFail:() -> Void) { 
    var geoCoder = CLGeocoder(); 

    var params = [ 
      String(kABPersonAddressZIPKey): zip, 
      String(kABPersonAddressCountryCodeKey): "US", 
    ] 

    geoCoder.geocodeAddressDictionary(params) { 
     (plasemarks, error) -> Void in 
     var plases = plasemarks as? Array<CLPlacemark> 

     if plases != nil && plases?.count > 0 { 
      var firstPlace = plases?[0] 

      var city = firstPlace?.addressDictionary[String(kABPersonAddressCityKey)] as? String 
      var state = firstPlace?.addressDictionary[String(kABPersonAddressStateKey)] as? String 
      var country = firstPlace?.addressDictionary[String(kABPersonAddressCountryKey)] as? String // US 

      onSuccess(city != nil ? city! : "", state != nil ? state! : "") 
      return; 
     } 

     onFail() 
    } 
} 

stesso con swift, non posso aggiungere questo come commento (punti non elaborati)

3

Ecco la versione Swift 3 con tutte le correzioni di cui sopra.

0

Ecco la versione Swift 4, con un'opportuna gestione degli optional come bonus. Da utilizzare se si desidera specificare manualmente il paese del codice postale interrogato.

private func zipToAddress(zip: String?, onSuccess: @escaping (String, String) -> Void, onFail: ((Error?) -> Void)?) { 

    guard let zip = zip else { 
     onFail?(nil) 
     return 
    } 

    let geoCoder = CLGeocoder() 

    let params: [String: Any] = [ 
     String(CNPostalAddressPostalCodeKey): zip, 
     String(CNPostalAddressISOCountryCodeKey): "US" 
     ] 

    geoCoder.geocodeAddressDictionary(params) { placemarks, error -> Void in 
     /// Read CLPlacemark documentation to see all available fields 
     if let place = placemarks?[0], let city = place.locality, let state = place.administrativeArea { 
      onSuccess(city, state) 
     } else { 
      onFail?(error) 
     } 
    } 
} 

Ed ecco la soluzione basata sulla risposta di Nathan. Da utilizzare per interrogare la città e l'area amministrativa, in base alle impostazioni locali dell'utente.

private func localZipToAddress(zip: String?, onSuccess: @escaping (String, String) -> Void, onFail: ((Error?) -> Void)?) { 

    guard let zip = zip else { 
     onFail?(nil) 
     return 
    } 

    CLGeocoder().geocodeAddressString(zip) { placemarks, error in 
     if let result = placemarks?.first, let city = result.locality, let state = result.administrativeArea { 
      onSuccess(city, state) 
     } else { 
      onFail?(error) 
     } 
    } 
} 
Problemi correlati