Traçando rotas no MKMapView com o iOS
Autor: João Henrique | Publicado: 2011-07-15T00:13:00-03:00

A um tempinho atrás eu tive que traçar uma rota de um ponto a outro no MKMapView em uma aplicação para iPhone que eu estava desenvolvendo e mesmo achando que poderia ser muito simples depois fui descobrir que não era tanto assim. Porque é muito simples mostrarmos um ou vários pontos no MKMapView, mas quando estamos falando de rotas estamos falando de dezenas ou milhares de pontos para termos uma rota correta. 

Bom, após um pouco de pesquisa eu descobri que o Google (Lógico!) tem um webservice que retorna um arquivo do tipo *.kml, e que este arquivo pode ser importado pelo Google Earth, Google Maps ou mesmo parseado pelo iOS e passadas as informações para o MKMapView, e foi isso que eu fiz e vou mostrar aqui como.

Primeira coisa a fazer é baixar o componente que eu uso para parserar o arquivo KML e passa-lo para o MKMapView.

O que eu fiz foi:
1. Acessar o webservice do Google para capturar o arquivo com as informações da rota
- Eu usei a biblioteca ASIHTTPRequest para acessar o webservice do Google e capturar o arquivo: http://allseeing-i.com/ASIHTTPRequest/
2. Salvar o arquivo localmente no iPhone
3. Acessar o arquivo e usar o KMLParser para parsear os dados da rota
4. Passar as informações para MKMapView
5. Apagar o arquivo para não sobrecarregar o iPhone.

LINK PARA KMLPARSER

1. Deste componente você só precisa importar para o seu projeto os arquivos:
- KMLParser.h e KMLParser.m
- Importar "#import "KMLParser.h" no arquivo que for usar

2. Acessando o Webservice:

NSString *strUrl = [NSString stringWithFormat:@"http://maps.google.com/maps?f=d&amp;source=s_d&amp;saddr=%@,+%@&amp;daddr=%@,+%@&amp;hl=en&amp;geocode=FWikz_4dDKBh_SnRH9PyzZmmADFdudOx0L-gAA%3BFQfB0P4d2a1h_SlxF9ueiZqmADHoONBTqE_fYQ&amp;mra=ls&amp;ie=UTF8&amp;z=13&amp;output=kml", STRING_ENDERECO_ORIGEM, STRING_CIDADE_ESTADO_PAIS, STRING_ENDERECO_DESTINO, STRING_CIDADE_ESTADO_PAIS];&nbsp;// Download and write to file
NSURL *url = [NSURL URLWithString:[strUrl stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];


ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request addRequestHeader:@"Content-Type" value:@"application/vnd.google-earth.kml+xml; charset=UTF-8"];
[request addRequestHeader:@"Content-Encoding" value:@"gzip"];
[request addRequestHeader:@"User-Agent" value:@"ASIHTTPRequest"];
[request setDelegate:self];
[request startSynchronous];
3. CAPTURAR O ARQUIVO RETORNADO PELO WEBSERVICE E SALVANDO LOCALMENTE

- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
//NSString *responseString = [request responseString];


// Use when fetching binary data
NSData *responseData = [request responseData];
NSString *documentsPath = [Util applicationDocumentsDirectory];
NSString *filePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.kml",STRING_NOME_DO_ARQUIVO]];
[responseData writeToFile:filePath atomically:YES];


}- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];


UIAlertView *alerta = [[UIAlertView alloc] initWithTitle:@"Tarifador de Taxi" 
message:@"Não foi possivel encontrar endereço.\n Sugestão: Tente sem acentuação." 
delegate:self 
cancelButtonTitle:@"Fechar" 
otherButtonTitles:nil];
[alerta show];
[alerta release];
}
4. DECLARAR COMPONENTES A SEREM UTILIZADOS NO ARQUIVO .H

//NAO ESQUEÇA DE DECLARAR A PROPRIEDADE TAMBEM.
//EU UTILIZEI O INTERFACE BUILDER PARA QUE EU NÃO PRECISE FICAR CRIANDO O MKMAPVIEW NO CÓDIGO
MKMapView *map;
//NAO ESQUEÇA DE DECLARAR A PROPRIEDADE TAMBEM.
KMLParser *kml;
5. MOSTRANDO A ROTA NO MAPA

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.


self.title = @"Mapa";


kml = [[KMLParser parseKMLAtPath:STRING_CAMINHO_DO_ARQUIVO] retain];


// Add all of the MKOverlay objects parsed from the KML file to the map.
NSArray *overlays = [kml overlays];
[map addOverlays:overlays];


// Add all of the MKAnnotation objects parsed from the KML file to the map.
NSArray *annotations = [kml points];
[map addAnnotations:annotations];


// Walk the list of overlays and annotations and create a MKMapRect that
// bounds all of them and store it into flyTo.
MKMapRect flyTo = MKMapRectNull;
for (id  overlay in overlays) {
if (MKMapRectIsNull(flyTo)) {
flyTo = [overlay boundingMapRect];
} else {
flyTo = MKMapRectUnion(flyTo, [overlay boundingMapRect]);
}
}

for (id  annotation in annotations) {
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
if (MKMapRectIsNull(flyTo)) {
flyTo = pointRect;
} else {
flyTo = MKMapRectUnion(flyTo, pointRect);
}
}

// Position the map so that all overlays and annotations are visible on screen.
map.visibleMapRect = flyTo;
}


#pragma mark MKMapViewDelegate


- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay
{
return [kml viewForOverlay:overlay];
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation
{
return [kml viewForAnnotation:annotation];
}
Acho que é isso pessoal. Qualquer duvida estou a disposição...