通过iOS中的邮政编码自动填充城市和州

时间:2014-04-30 11:41:44

标签: ios objective-c google-api

我认为我有三个文本域。 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?
}

6 个答案:

答案 0 :(得分:17)

我尽量避免使用谷歌的服务,因为他们倾向于按一定的使用水平收费。以下是使用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
        }
    }];
}

答案 1 :(得分:10)

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

如果您的zipcode变量为32000,您将获得this JSON结果:

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

答案 2 :(得分:5)

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

答案 3 :(得分:3)

虽然alex_c和ar-studios的答案运作良好,但如果您不想与AddressBookUI或字典混淆,您可以在{{1}上使用geocodeAddressString:completionHandler:方法仅传递足够用于查找的邮政编码:

geocoder

在斯威夫特:

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

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

答案 4 :(得分:2)

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

答案 5 :(得分:1)

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相同,我不能将其添加为注释(点不会引用)