我的视图中有三个文本字段。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相同,我不能将其添加为注释(点数不够(