尝试在MKMapView中加载创建的Map [英] Try to load a created Map in MKMapView

查看:81
本文介绍了尝试在MKMapView中加载创建的Map的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图加载我在Google-Maps中使用kml文件创建的地图。 Google Maps链接。我不得不说它只是一个例子,但它是相同的原理。

最简单的方法是加载WebView,但这在我眼中是丑陋的。



谢谢阅读我的问题!



祝好运CTS

解决方案

a KML 转换为 MKMapView


  1. 添加必要的框架 MapKit.framework CoreLocation.framework )到您的目标;


  2. 加载和解析KML;

  3. 根据KML创建注释;和


  4. 将地图的 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:

  1. Add the necessary frameworks (MapKit.framework and CoreLocation.framework) to your target;

  2. Load and parse the KML;

  3. Create your annotations on the basis of the KML; and

  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆