目标c-在iOS中从邮政编码自动填充城市和州



我的视图中有三个文本字段。1.邮编,2。城市和3。状态

如何在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?
}

我尽量避开谷歌的服务,因为它们往往按一定的使用水平收费。以下是使用苹果框架的解决方案:

 #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
        }
    }];
}

使用Google GeoCoding API提取信息,如果您想发送邮政编码以接收其他信息,请使用此:

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);

如果您的邮政编码变量是32000,您将得到以下JSON结果:

您可以解析这个json来提取您想要的任何信息,包括国家、城市、经度、纬度等

a-r-studios的答案很准确,因为它没有引入对谷歌服务的依赖。

然而,我也会根据用户的输入或只有在有意义的情况下才限制国家代码。不限制它会产生不可预测的结果,因为地理编码器可以从不同的国家返回多个点击。

 #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
        }
    }];
}

虽然alex_c和a-r-studios的答案很好,但如果你不想对AddressBookUI或字典大惊小怪,你可以简单地在geocoder上使用geocodeAddressString:completionHandler:方法,只需传入邮政编码即可进行查找:

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

Swift:

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

这是Swift 3版本,包含了所有上述更正。

func zipToAddress(zip: String, onSuccess: @escaping (String, String, String) -> Void, onFail: @escaping () -> Void) {
    let geoCoder = CLGeocoder();
    let params = [
        String(CNPostalAddressPostalCodeKey): zip,
        String(CNPostalAddressISOCountryCodeKey): "US",
        ]
    geoCoder.geocodeAddressDictionary(params) {
        (plasemarks, error) -> Void in
        if let plases = plasemarks {
            if plases.count > 0 {
                let firstPlace = plases[0]
                print( "City (firstPlace.locality) state (firstPlace.administrativeArea) and country (firstPlace.country) and iso country (firstPlace.country)")
                let city = firstPlace.locality
                let state = firstPlace.administrativeArea
                let country = firstPlace.country
                onSuccess(city != nil ? city! : "", state != nil ? state! : "", country ?? "Not found")
                return;
            }
        }
        onFail()
    }
}

这是Swift 4的版本,附带了适当的选项处理。如果要手动指定查询的邮政编码所在的国家/地区,请使用此选项。

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)
        }
    }
}

这是基于Nathan答案的解决方案。使用此选项可以根据用户区域设置查询城市和行政区域。

 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)
        }
    }
}
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()
    }
}

与swift相同,我不能将其添加为注释(点数不够(

相关内容

  • 没有找到相关文章

最新更新