我认为我有三个文本域。 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?
}
答案 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相同,我不能将其添加为注释(点不会引用)