oscarimonbox
1/9/2017 - 9:33 AM

Añadir autocompletado de dirección en mapa

Añadir autocompletado de dirección en mapa

1) Añadir a Podfile : pod 'MLPAutoCompleteTextField'
2) Añadir campo Textfield a pantalla y asignar la clase MLPAutoCompleteTextField

3) Añadir a .h
#import <MLPAutoCompleteTextField/MLPAutoCompleteTextField.h>

delegates: UIActionSheetDelegate, MLPAutoCompleteTextFieldDelegate, MLPAutoCompleteTextFieldDataSource, UITextFieldDelegate

@property (weak, nonatomic) IBOutlet MLPAutoCompleteTextField *tfLocationAddress;
@property (strong, nonatomic) CLGeocoder *geocoder;
@property (strong, nonatomic) GMSGeocoder *reverseGeocoder;
@property (strong, nonatomic) NSArray *placemarksResult;

4) Añadir a .m:
#import "AutoCompleteAddress.h"

5) Añadir clase de AutoCompleteAddress

//
//  AutoCompleteAddress.h
//

#import <Foundation/Foundation.h>
#import "MLPAutoCompletionObject.h"
#import <CoreLocation/CoreLocation.h>

@interface AutoCompleteAddress : NSObject <MLPAutoCompletionObject>

@property (strong, nonatomic) CLPlacemark* address;

@end

-------------------

//
//  AutoCompleteAddress.m
//

#import "AutoCompleteAddress.h"

@implementation AutoCompleteAddress

-(NSString *)autocompleteString{
    NSString *addressString = @"";
    
    if(_address){
        if (!([self.address thoroughfare]  == (id)[NSNull null] || [self.address thoroughfare].length == 0 )){
            addressString = [NSString stringWithFormat:@"%@", [self.address thoroughfare]];
        }
        if (!([self.address subThoroughfare]  == (id)[NSNull null] || [self.address subThoroughfare].length == 0 )){
            if(addressString.length>0){
                addressString = [addressString stringByAppendingString:@", "];
            }
            addressString = [addressString stringByAppendingString:[self.address subThoroughfare]];
        }
        if (!([self.address locality]  == (id)[NSNull null] || [self.address locality].length == 0 )){
            if(addressString.length>0){
                addressString = [addressString stringByAppendingString:@", "];
            }
            addressString = [addressString stringByAppendingString:[self.address locality]];
        }
        if (!([self.address country]  == (id)[NSNull null] || [self.address country].length == 0 )){
            if(addressString.length>0){
                addressString = [addressString stringByAppendingString:@", "];
            }
            addressString = [addressString stringByAppendingString:[self.address country]];
        }
        
    }
    
    return addressString;
}

@end




6) Añadir array de resultados en .m:
@implementation MapPageView{
    NSMutableArray* results;
}


7) Añadir a didLoad o similar en .m:

    self.tfLocationAddress.delegate = self;
    [self.tfLocationAddress setAutoCompleteTableAppearsAsKeyboardAccessory:YES];
    [self.tfLocationAddress setAutoCompleteTableCornerRadius:5];
    [self.tfLocationAddress setAutoCompleteTableBorderWidth:1];
    [self.tfLocationAddress setAutoCompleteTableBorderColor:[UIColor lightGrayColor]];
    [self.tfLocationAddress setAutoCompleteDataSource:self];
    [self.tfLocationAddress setAutoCompleteDelegate:self];
    
    self.tfLocationAddress.autoCompleteTableBackgroundColor = [UIColor whiteColor];
    [self.tfLocationAddress setAutoCompleteRegularFontName:FONT];
    [self.tfLocationAddress setAutoCompleteTableCellTextColor:[UIColor blackColor]];
    self.tfLocationAddress.maximumNumberOfAutoCompleteRows = 5;
    
    self.tfLocationAddress.clearButtonMode = UITextFieldViewModeWhileEditing;

    self.reverseGeocoder = [GMSGeocoder geocoder];

8) Añadir a .m
#pragma mark - MLPAutoCompleteTextField DataSource
-(void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField possibleCompletionsForString:(NSString *)string completionHandler:(void (^)(NSArray *))handler
{
    NSString* query = textField.text;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        
        if(![query isEqualToString:self.tfLocationAddress.text]){
            return;
        }
        [self.geocoder geocodeAddressString:query completionHandler:^(NSArray *placemarks, NSError *error) {
            
            results = [NSMutableArray new];
            
            if(placemarks){
                
                self.placemarksResult = [[NSArray alloc]init];
                self.placemarksResult = placemarks;
                
                for( CLPlacemark *address in placemarks) {
                    
                    AutoCompleteAddress* res = [AutoCompleteAddress new];
                    res.address = address;
                    [results addObject:res];
                }
            }
            if([query isEqualToString:self.tfLocationAddress.text]){
                handler(results);
            }
            
            
        }];
        
        
    });
}

#pragma mark - MLPAutoCompleteTextField Delegate

- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
  didSelectAutoCompleteString:(NSString *)selectedString
       withAutoCompleteObject:(id<MLPAutoCompletionObject>)selectedObject
            forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(selectedObject && [selectedObject isKindOfClass:[AutoCompleteAddress class]]){
        NSLog(@"selected object from autocomplete menu %@ with string %@", selectedObject, [selectedObject autocompleteString]);
        
        CLPlacemark* place = ((AutoCompleteAddress*)selectedObject).address;
        [self.tfLocationAddress setText:[selectedObject autocompleteString]];
        
        
        [self.map animateToLocation:place.location.coordinate];
        
    } else {
        NSLog(@"selected string '%@' from autocomplete menu", selectedString);
    }
}


- (void)onSearch {
    
    [self.view endEditing:YES];
    
    [self.geocoder geocodeAddressString:self.tfLocationAddress.text completionHandler:^(NSArray *placemarks, NSError *error) {
        
        
        if([placemarks count]){
            
            if (([placemarks count]) == 1) {
                
                CLPlacemark* place = [placemarks firstObject];
                [self.map animateToLocation:place.location.coordinate];
                
            } else {
                
                self.placemarksResult = [[NSArray alloc]init];
                self.placemarksResult = placemarks;
                
                UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"select_location", nil)
                                                                   delegate:self
                                                          cancelButtonTitle:NSLocalizedString(@"cancel", nil)
                                                     destructiveButtonTitle:nil
                                                          otherButtonTitles:nil];
                
                int i=0;
                
                for( CLPlacemark *title in placemarks) {
                    AutoCompleteAddress* address = [AutoCompleteAddress new];
                    address.address = title;
                    
                    [popup addButtonWithTitle: [address autocompleteString]];
                    
                    i++;
                    if (i==3)
                        break;
                }
                
                popup.tag = 1;
                [popup showInView:self.view];
            }
            
        }
    }];
}

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    
    if (buttonIndex != 0) {
        CLPlacemark* place = [self.placemarksResult objectAtIndex:buttonIndex-1];
        [self.map animateToLocation:place.location.coordinate];
    }
    
}


#pragma mark - Map delegate

- (CLGeocoder *)geocoder {
    if (!_geocoder) {
        _geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}

-(void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position{
    
    NSLog(@"Cambio lat:%f, lon:%f", position.target.latitude, position.target.longitude);
    
    CLLocationCoordinate2D pos = CLLocationCoordinate2DMake(position.target.latitude, position.target.longitude);
    
    [self.reverseGeocoder reverseGeocodeCoordinate:pos completionHandler:^(GMSReverseGeocodeResponse *response, NSError *error){
        
        [self.tfLocationAddress setText:@""];
        
        for (GMSAddress* addressObj in [response results]) {
            
            NSLog(@"Street found: %@", addressObj.lines);
            
            if ([addressObj.lines count]==2){
                [self.tfLocationAddress setText: [NSString stringWithFormat:@"%@ %@", addressObj.lines[0], addressObj.lines[1]]];
            } else{
                [self.tfLocationAddress setText: [NSString stringWithFormat:@"%@", addressObj.lines[0]]];
            }
            
            break;
        }
        
        
    }];
}


#pragma-mark Keyboard

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    
    if ([textField isEqual:self.tfLocationAddress]) {
        [textField resignFirstResponder];
        [self performSelector:@selector(onSearch) withObject:nil];
    }
    
    return YES;
}