尝试在MKMapView中加载创建的Map [英] Try to load a created Map in MKMapView
问题描述
我试图加载我在Google-Maps中使用kml文件创建的地图。 Google Maps链接。我不得不说它只是一个例子,但它是相同的原理。
最简单的方法是加载WebView,但这在我眼中是丑陋的。
谢谢阅读我的问题!
祝好运CTS
a KML
转换为 MKMapView
:
-
添加必要的框架(
MapKit.framework
和CoreLocation.framework
)到您的目标; -
加载和解析KML;
-
根据KML创建注释;和
-
将地图的
region
设置为包含注释。
因此,这可能看起来像:
#导入< MapKit / MapKit.h>
$ b $ - (void)loadKml:(NSURL *)url
{
//解析kml
Parser * parser = [[Parser alloc] initWithContentsOfURL:URL];
parser.rowElementName = @地标;
parser.elementNames = @ [@name,@Snippet,@coordinates,@description];
parser.attributeNames = nil;
[解析器解析];
//为每个条目添加注释
(NSDictionary * locationDetails in parser.items)
{
MKPointAnnotation * annotation = [[ MKPointAnnotation alloc] init];
annotation.title = locationDetails [@name];
annotation.subtitle = locationDetails [@Snippet];
NSArray * coordinates = [locationDetails [@coordinates] componentsSeparatedByString:@,];
annotation.coordinate = CLLocationCoordinate2DMake([coordinates [1] floatValue],[coordinates [0] floatValue]);
[self.mapView addAnnotation:annotation];
}
//更新地图以关注包含所有注释的区域
MKCoordinateRegion region;
if([self.mapView.annotations count]> 1)
{
region = [self regionForAnnotations:self.mapView.annotations];
region = MKCoordinateRegionMake(region.center,MKCoordinateSpanMake(region.span.latitudeDelta * 1.05,region.span.longitudeDelta * 1.05)); //将区域扩大5%
}
else
{
id< MKAnnotation> annotation = self.mapView.annotations [0];
region = MKCoordinateRegionMakeWithDistance(annotation.coordinate,100.0,100.0);
}
[self.mapView setRegion:region animated:YES];
我的解析器
类仅仅是我写的 NSXMLParser
子类,它会在每个 rowElementName
,并且对于每一行,它将获取 elementNames
数组中列出的元素。
Parser.h:
#import< Foundation / Foundation.h>
@interface解析器:NSXMLParser
@property(nonatomic,strong)NSString * rowElementName; //这是识别XML
@property(nonatomic,strong)NSArray * attributeNames中的新数据行的元素名称; //这是我们可能想要为该元素名称检索的属性数组
@property(nonatomic,strong)NSArray * elementNames; //这是我们检索值的子元素名称列表
@property(nonatomic,strong)NSMutableArray * items; //解析后,这是解析项目的数组
@end
Parser.m:
#importParser.h
@interface Parser()< ; NSXMLParserDelegate>
@property(nonatomic,strong)NSMutableDictionary * item; //解析时,这是当前正在解析的项目
@property(nonatomic,strong)NSMutableString * elementValue; //这是被解析的项目中的元素
@end
@implementation解析器
$ b $ - (id)initWithContentsOfURL:(NSURL *) url
{
self = [super initWithContentsOfURL:url];
if(self)
{
self.delegate = self;
}
返回自我;
$ b $ - (id)initWithData:(NSData *)data
{
self = [super initWithData:data];
if(self)
{
self.delegate = self;
}
返回自我;
$ b - (id)initWithStream:(NSInputStream *)stream
{
self = [super initWithStream:stream];
if(self)
{
self.delegate = self;
}
返回自我;
}
#pragma mark - NSXMLParserDelegate方法
$ b $ - (void)parserDidStartDocument:(NSXMLParser *)解析器
{
self.items = [[NSMutableArray alloc] init];
if(!self.rowElementName)
NSLog(@%s Warning:无法指定行标识符元素名称,__FUNCTION__); (NSXMLParser *)解析器didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName属性:(NSDictionary * )attributeDict
{
if([elementName isEqualToString:self.rowElementName])
{
self.item = [[NSMutableDictionary alloc] init];
for(NSString * attributeName in self.attributeNames)
{
id attributeValue = [attributeDict valueForKey:attributeName];
if(attributeValue)
[self.item setObject:attributeValue forKey:attributeName];
else if([self.elementNames containsObject:elementName])
{
self.elementValue = [[NSMutableString alloc] init]; (NSXMLParser *)解析器foundCharacters:(NSString *)string
{
if(self.elementValue)
$ )
{
[self.elementValue appendString:string]; (NSXMLParser *)解析器didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName(b)
{
if([elementName isEqualToString:self.rowElementName])
{
[self.items addObject:self.item];
self.item = nil;
}
else if([self.elementNames containsObject:elementName])
{
[self.item setValue:self.elementValue forKey:elementName];
self.elementValue = nil;
}
}
@end
最后,我的 loadKml
使用的唯一其他实用程序方法是 regionForAnnotations
,它根据一系列注释定义一个区域。 Rob Mooney写了一个简单的例程来做到这一点:
- (MKCoordinateRegion)regionForAnnotations:(NSArray *)annotations {
CLLocationDegrees minLat = 90.0;
CLLocationDegrees maxLat = -90.0;
CLLocationDegrees minLon = 180.0;
CLLocationDegrees maxLon = -180.0;
(注释中的id< MKAnnotation>注释){
if(annotation.coordinate.latitude< minLat){
minLat = annotation.coordinate.latitude;
}
if(annotation.coordinate.longitude< minLon){
minLon = annotation.coordinate.longitude;
}
if(annotation.coordinate.latitude> maxLat){
maxLat = annotation.coordinate.latitude;
}
if(annotation.coordinate.longitude> maxLon){
maxLon = annotation.coordinate.longitude;
}
}
MKCoordinateSpan span = MKCoordinateSpanMake(maxLat - minLat,maxLon - minLon);
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((maxLat - span.latitudeDelta / 2),maxLon - span.longitudeDelta / 2);
return MKCoordinateRegionMake(center,span);
}
I am trying to load my Map which I created with a kml File in Google-Maps. The Google Maps Link. I have to say it is only an example, but it is the same principle.
The easiest way is to load in a WebView, but that is ugly in my eyes.
Thank you for reading my Question!
Best regards CTS
To load a KML
into a MKMapView
:
Add the necessary frameworks (
MapKit.framework
andCoreLocation.framework
) to your target;Load and parse the KML;
Create your annotations on the basis of the KML; and
Set your map's
region
to encompass the annotations.
Thus, that might look like:
#import <MapKit/MapKit.h>
- (void)loadKml:(NSURL *)url
{
// parse the kml
Parser *parser = [[Parser alloc] initWithContentsOfURL:url];
parser.rowElementName = @"Placemark";
parser.elementNames = @[@"name", @"Snippet", @"coordinates", @"description"];
parser.attributeNames = nil;
[parser parse];
// add annotations for each of the entries
for (NSDictionary *locationDetails in parser.items)
{
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.title = locationDetails[@"name"];
annotation.subtitle = locationDetails[@"Snippet"];
NSArray *coordinates = [locationDetails[@"coordinates"] componentsSeparatedByString:@","];
annotation.coordinate = CLLocationCoordinate2DMake([coordinates[1] floatValue], [coordinates[0] floatValue]);
[self.mapView addAnnotation:annotation];
}
// update the map to focus on the region that encompasses all of your annotations
MKCoordinateRegion region;
if ([self.mapView.annotations count] > 1)
{
region = [self regionForAnnotations:self.mapView.annotations];
region = MKCoordinateRegionMake(region.center, MKCoordinateSpanMake(region.span.latitudeDelta * 1.05, region.span.longitudeDelta * 1.05)); // expand the region by 5%
}
else
{
id<MKAnnotation> annotation = self.mapView.annotations[0];
region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 100.0, 100.0);
}
[self.mapView setRegion:region animated:YES];
}
My Parser
class is just a NSXMLParser
subclass that I've written that will create an array of items
one per occurrence of rowElementName
, and for each row, it will grab the elements listed in the elementNames
array.
Parser.h:
#import <Foundation/Foundation.h>
@interface Parser : NSXMLParser
@property (nonatomic, strong) NSString *rowElementName; // this is the element name that identifies a new row of data in the XML
@property (nonatomic, strong) NSArray *attributeNames; // this is the array of attributes we might want to retrieve for that element name
@property (nonatomic, strong) NSArray *elementNames; // this is the list of sub element names for which we're retrieving values
@property (nonatomic, strong) NSMutableArray *items; // after parsing, this is the array of parsed items
@end
Parser.m:
#import "Parser.h"
@interface Parser () <NSXMLParserDelegate>
@property (nonatomic, strong) NSMutableDictionary *item; // while parsing, this is the item currently being parsed
@property (nonatomic, strong) NSMutableString *elementValue; // this is the element within that item being parsed
@end
@implementation Parser
- (id)initWithContentsOfURL:(NSURL *)url
{
self = [super initWithContentsOfURL:url];
if (self)
{
self.delegate = self;
}
return self;
}
- (id)initWithData:(NSData *)data
{
self = [super initWithData:data];
if (self)
{
self.delegate = self;
}
return self;
}
- (id)initWithStream:(NSInputStream *)stream
{
self = [super initWithStream:stream];
if (self)
{
self.delegate = self;
}
return self;
}
#pragma mark - NSXMLParserDelegate methods
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.items = [[NSMutableArray alloc] init];
if (!self.rowElementName)
NSLog(@"%s Warning: Failed to specify row identifier element name", __FUNCTION__);
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:self.rowElementName])
{
self.item = [[NSMutableDictionary alloc] init];
for (NSString *attributeName in self.attributeNames)
{
id attributeValue = [attributeDict valueForKey:attributeName];
if (attributeValue)
[self.item setObject:attributeValue forKey:attributeName];
}
}
else if ([self.elementNames containsObject:elementName])
{
self.elementValue = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.elementValue)
{
[self.elementValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:self.rowElementName])
{
[self.items addObject:self.item];
self.item = nil;
}
else if ([self.elementNames containsObject:elementName])
{
[self.item setValue:self.elementValue forKey:elementName];
self.elementValue = nil;
}
}
@end
Finally, the only other utility method that my loadKml
uses is regionForAnnotations
, which defines a region based upon a series of annotations. Rob Mooney wrote a simple routine to do that:
- (MKCoordinateRegion)regionForAnnotations:(NSArray *)annotations {
CLLocationDegrees minLat = 90.0;
CLLocationDegrees maxLat = -90.0;
CLLocationDegrees minLon = 180.0;
CLLocationDegrees maxLon = -180.0;
for (id <MKAnnotation> annotation in annotations) {
if (annotation.coordinate.latitude < minLat) {
minLat = annotation.coordinate.latitude;
}
if (annotation.coordinate.longitude < minLon) {
minLon = annotation.coordinate.longitude;
}
if (annotation.coordinate.latitude > maxLat) {
maxLat = annotation.coordinate.latitude;
}
if (annotation.coordinate.longitude > maxLon) {
maxLon = annotation.coordinate.longitude;
}
}
MKCoordinateSpan span = MKCoordinateSpanMake(maxLat - minLat, maxLon - minLon);
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((maxLat - span.latitudeDelta / 2), maxLon - span.longitudeDelta / 2);
return MKCoordinateRegionMake(center, span);
}
这篇关于尝试在MKMapView中加载创建的Map的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!