我正在使用这个问题中的代码 NSURLConnection download large file (>40MB)下载 KML 文件并使用 Apple 的 KMLViewer 在我的 MKMap 中加载数据。KML 文件很小 <200KB,所以 KMLViewer 就可以了。问题中提供的代码也应该很好,除了当我单击按钮时(这应该发出 url 的请求,然后将数据加载到 map 中) map 刚好到达位置 0,0,缩放非常大,所以我只能看到一张黑色 map 。出了什么问题?我应该怎么办? 这是代码: (顺便说一句,我有两个连接,因为一个连接使用 JSON 从 UIsearchBar 获取 Google 搜索结果中的位置。)
编辑 1
//In the ViewController.m
-(void) searchCoordinatesForAddress:(NSString *)inAddress //for Google location search
{
NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@?output=json",inAddress];
[urlString setString:[urlString stringByReplacingOccurrencesOfString:@" " withString:@"+"]];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[webData setLength:0]; //webData in the header file
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
if ( connection = theConnection ) //theConnection is created before
{
[webData appendData:data];
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *results = [jsonString JSONValue];
NSArray *placemark = [results objectForKey:@"Placemark"];
NSArray *coordinates = [[placemark objectAtIndex:0] valueForKeyPath:@"Point.coordinates"];
double longitude = [[coordinates objectAtIndex:0] doubleValue];
double latitude = [[coordinates objectAtIndex:1] doubleValue];
NSLog(@"Latitude - Longitude: %f %f", latitude, longitude);
[self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude];
[jsonString release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *fileName = [[[NSURL URLWithString:kmlStr] path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:fileName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
[webData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(@" Error in writing file %@' : \n %@ ", filePath , writeError );
return;
}
NSLog(@"%@",fileURL);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error !" message:@"Error has occured, please verify internet connection.." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
-(IBAction)showKmlData:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"KMLGenerator" ofType:@"kml"];
kml = [[KMLParser parseKMLAtPath:path] retain];
NSArray *overlays = [kml overlays];
[mapview addOverlays:overlays];
NSArray *annotations = [kml points];
[mapview addAnnotations:annotations];
MKMapRect flyTo = MKMapRectNull;
for (id <MKOverlay> overlay in overlays) {
if (MKMapRectIsNull(flyTo)) {
flyTo = [overlay boundingMapRect];
} else {
flyTo = MKMapRectUnion(flyTo, [overlay boundingMapRect]);
}
}
for (id <MKAnnotation> 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);
}
}
mapview.visibleMapRect = flyTo;
}
EDIT 2 我做了修改,现在它哪儿也去不了,它崩溃了,因为它找不到 KMLGenerator.kml 文件(路径)
-(void)showData
{
NSString *url = /*kmlStr;*/@"http://www.ikub.al/hartav2/handlers/kmlgenerator.ashx?layerid=fc77a5e6-5985-4dd1-9309-f026d7349064&kml=1";
NSURL *path = [NSURL URLWithString:url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:path];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
theConnection = connection;
[connection release];
[request release];
}
//Search Coordinates for address entered in the searchBar
-(void) searchCoordinatesForAddress:(NSString *)inAddress
{
NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@?output=json",inAddress];
[urlString setString:[urlString stringByReplacingOccurrencesOfString:@" " withString:@"+"]];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength:0]; //Here i get an alert: NSData may not respond to -setLength
//webData is a NSData object.
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data]; //Here i get an alert: NSData may not respond to -appendData
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if ( connection == theConnection ) //"theConnection" is for kml file download
{
NSString *fileName = [[[NSURL URLWithString:kmlStr] path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:fileName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
[webData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(@" Error in writing file %@' : \n %@ ", filePath , writeError );
return;
}
NSLog(@"%@",fileURL);
}
else //it's a geocoding result
{
NSString *jsonString = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];
NSDictionary *results = [jsonString JSONValue];
//check the Google geocode error code before looking for coordinates...
NSDictionary *statusDict = [results objectForKey:@"Status"];
NSNumber *errorCode = [statusDict objectForKey:@"code"];
if ([errorCode intValue] == 200) //200 is "success"
{
NSArray *placemark = [results objectForKey:@"Placemark"];
NSArray *coordinates = [[placemark objectAtIndex:0] valueForKeyPath:@"Point.coordinates"];
double longitude = [[coordinates objectAtIndex:0] doubleValue];
double latitude = [[coordinates objectAtIndex:1] doubleValue];
NSLog(@"Latitude - Longitude: %f %f", latitude, longitude);
[self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude];
}
else
{
NSLog(@"geocoding error %@", errorCode);
}
[jsonString release];
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error!" message:@"Error has occured, please verify internet connection..." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
- (IBAction)showKmlData:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"KMLGenerator" ofType:@"kml"];
kml = [[KMLParser parseKMLAtPath:path] retain];
NSArray *annotationsImmut = [kml points];
NSMutableArray *annotations = [annotationsImmut mutableCopy];
//[mapview addAnnotations:annotations];
[self filterAnnotations:annotations];
MKMapRect flyTo = MKMapRectNull;
for (id <MKAnnotation> 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);
}
}
mapview.visibleMapRect = flyTo;
}
最佳答案
仍然很难查明原因,但您发布的代码存在一些问题。
首先,在didReceiveData
中,这一行可能不是你想要的:
if ( connection = theConnection ) //theConnection is created before
单个 =
正在执行赋值而不是相等检查(即 ==
)。
然而,解决这个问题并不是解决方案(另一个问题在 connectionDidFinishLoading
中)。
didReceiveData
方法不是处理地理编码 JSON 结果的正确位置。 didReceiveData
方法可以为单个 url 请求调用多次。因此,地理编码结果(就像 kml 文件一样)可能会以多个 block 的形式交付,而这些 block 无法在该方法中单独处理。该方法中的 data
可能是完整结果的部分流,对处理没有意义。您应该只将数据附加到 NSMutableData 对象,或者如对链接问题的回答所建议的那样,将数据写入文件。
数据只能在connectionDidFinishLoading
方法中处理/解析。
由于您对 kml 文件下载和地理编码使用相同的连接委托(delegate),因此它们都调用相同的 connectionDidFinishLoading
方法。在该方法中,您不会检查正在调用哪个连接。
本地理编码 url 请求完成并调用 connectionDidFinishLoading
时,该方法获取 webData
中的任何内容(可能是地理编码结果或空数据)并将其写入 kmlStr
文件。这可能是导致 kml 数据显示“无”的原因。
您必须将地理编码结果的处理移动到 connectionDidFinishLoading
并在那里检查哪个连接正在调用它。
例如:
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if ( connection == theConnection ) //"theConnection" is for kml file download
{
NSString *fileName = [[[NSURL URLWithString:kmlStr] path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:fileName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
[webData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(@" Error in writing file %@' : \n %@ ", filePath , writeError );
return;
}
NSLog(@"%@",fileURL);
}
else //it's a geocoding result
{
NSString *jsonString = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];
NSDictionary *results = [jsonString JSONValue];
//check the Google geocode error code before looking for coordinates...
NSDictionary *statusDict = [results objectForKey:@"Status"];
NSNumber *errorCode = [statusDict objectForKey:@"code"];
if ([errorCode intValue] == 200) //200 is "success"
{
NSArray *placemark = [results objectForKey:@"Placemark"];
NSArray *coordinates = [[placemark objectAtIndex:0] valueForKeyPath:@"Point.coordinates"];
double longitude = [[coordinates objectAtIndex:0] doubleValue];
double latitude = [[coordinates objectAtIndex:1] doubleValue];
NSLog(@"Latitude - Longitude: %f %f", latitude, longitude);
[self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude];
}
else
{
NSLog(@"geocoding error %@", errorCode);
}
[jsonString release];
}
}
(最好避免对多个连接使用相同的委托(delegate)。将地理编码移出到另一个具有自己的连接对象和委托(delegate)方法的类会更清晰。顺便说一下,iOS5 内置了地理编码,因此您不需要自己做。请参阅 CLGeocoder 类。)
我添加了对 Google 错误代码的检查。查询的地址可能没有返回任何结果,在这种情况下将没有地标坐标,在这种情况下纬度和经度将设置为零。这是 map 转到 0,0 的另一个可能原因。
您似乎也在使用 deprecated v2 Google geocoder . This is the latest one但除非您需要支持 iOS4 或更早版本,否则您可能希望改用 CLGeocoder
。
关于iphone - 显示 kml 数据?不, map 将转到位置 (0,0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7954852/