热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FindingBusinessListingsandDisplayingwithMapKit–Part1

Inthisthreepartseries,Iwanttoshowyouhowyoucaneasilyshowauserbusinesslistingsbased

In this three part series, I want to show you how you can easily show a user business listings based on their current location. To do so we’ll be using the CoreLocation and MapKit Frameworks. First, we need a way to actually find nearby businesses. There are a number of third-party mapping API’s out there, some with paid subscription, but for a simpler application there is a simpler solution. For the first part in this series we are going to connect to the Google Maps service directly and retrieve xml output with which we will later use to populate MapKit. First, let’s take a look at the actual Google Maps call. It will look something like this:

http://maps.google.com/maps?q=Apple&mrt=yp&sll=26.1209,-80.1444&output=kml

With the Google Maps API there are a number of parameters you can use to get different information. In this case we are set the “q” param as the search keyword. Next we have the “mrt” param. This specifies what type of search you want to do. In the case we are setting this to “yp” which is short for “Yellow Pages”. This means we’ll be returned a list of business information much like a phone book look-up. Next we set the “sll” or “search latitude and longitude”. Finally, we specify the “output” type as “kml”. KML is based on XML standard and is used specifically to describe geographic data. For more on the available parameters, check out Google’s MapKi documentation.

NOTE: Typically JSON is the data format of choice for iphone because of it’s size and ease to parse. In this case, I found that XML was typically smaller in size, so it was my choice.

The first thing you should do is add the MapKit and CoreLocation frameworks to your project. Then, let’s just right into the MapDataParser class.

#import
#import "MapLocationVO.h"

 

@interface MapDataParser : NSObject
{
    BOOL isPlacemark;
   
    NSXMLParser *mapsDataParser;
    NSMutableString *currentElementValue;
    NSMutableArray *locationData;
    MapLocationVO *currentMapLocation;
    NSMutableString *currentElementName;
}

@property (nonatomic, retain) NSMutableArray *locationData;

-(void) getBusinessListingsByKeyword:(NSString *)keyword atLat:(float)lat atLng:(float)lng;
-(void) parseXMLFileAtURL:(NSString *)URL;

@end

Here we define the NSXMLParser and the set the NSXMLParserDelegate for the class. The locationData array is where other classes will later have access to the parsed data. Finally, we have the getBusinessListingsByKeyword method, which accepts the search term and the center latitude and longitude. Let’s take a look at how this is implemented.

#import "MapDataParser.h"
#import "MapLocationVO.h"

 


@implementation MapDataParser

@synthesize locationData;

-(void) getBusinessListingsByKeyword:(NSString *)keyword atLat:(float)lat atLng:(float)lng
{
    // Construct our maps call.
   
    [self parseXMLFileAtURL:[NSString stringWithFormat:@"http://maps.google.com/maps?q=%@&mrt=yp&sll=%g,%g&output=kml", [keyword stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding], lat, lng]];
}

- (void)parseXMLFileAtURL:(NSString *)URL
{  
    // parse file at url
   
    NSURL *xmlURL = [NSURL URLWithString:URL];
   
    mapsDataParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
    mapsDataParser.delegate = self;
    [mapsDataParser setShouldProcessNamespaces:NO];
    [mapsDataParser setShouldReportNamespacePrefixes:NO];
    [mapsDataParser setShouldResolveExternalEntities:NO];
   
    [mapsDataParser parse];
}

 - (void)parserDidStartDocument:(NSXMLParser *)parser
{
    // Parser has started so create locationData array to store MapLocation value objects
   
    if(self.locationData)
    {
        [self.locationData removeAllObjects];
    }
    else
    {
        self.locationData = [[NSMutableArray alloc] init];
    }
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    // Unable to reach the service, show error alert
   
    NSString * errorString = [NSString stringWithFormat:@"Unable to get map data. (Error code %i )", [parseError code]];
    UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"Placemark"])
    {
        // Placemark item found, prepare to save data to new MapLocationVO
       
        currentMapLocation = [[MapLocationVO alloc] init];
        isPlacemark = YES;
    }
    else
    {
        // Element other than Placemark found, store it for "foundCharacters" check
       
        [currentElementName release];
        currentElementName = nil;
        currentElementName = [[NSString alloc] initWithString:elementName];
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"Placemark"])
    {
        // Placemark element ended, store data
       
        isPlacemark = NO;
       
        NSLog(@"Map Item %i Added", [self.locationData count]);
        NSLog(@"Title: %@", currentMapLocation.locationTitle);
        NSLog(@"Snippet: %@", currentMapLocation.locationSnippet);
        NSLog(@"Coordinates: %@", currentMapLocation.mapLocation);
       
        [self.locationData addObject: currentMapLocation];
       
        [currentMapLocation release];
        currentMapLocation = nil;
    }  
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if(isPlacemark)
    {      
        // If we are currently in a Placemark element,
        // check if current is something we want to store
       
        if ([currentElementName isEqualToString:@"name"])
        {
            // Store Location Title
           
            if(!currentMapLocation.locationTitle)
            {
                currentMapLocation.locationTitle = [[NSMutableString alloc] initWithString:string];
            }
            else
            {
                [currentMapLocation.locationTitle appendString: string];
            }
        }
        else if ([currentElementName isEqualToString:@"Snippet"])
        {
            // Replace line breaks with new line
           
            currentMapLocation.locationSnippet = currentMapLocation.locationSnippet = [[NSMutableString alloc] initWithString:[string stringByReplacingOccurrencesOfString:@"
"
withString:@"\n"]];
        }
        else if ([currentElementName isEqualToString:@"coordinates"])
        {      
            // Create a coordinate array to use when allocating CLLocation.
            // We will use the CLLocation object later when populating the map
           
            NSArray *coordinatesList = [string componentsSeparatedByString:@","];
            currentMapLocation.mapLocation = [[CLLocation alloc] initWithLatitude:[[coordinatesList objectAtIndex:1] floatValue] longitude:[[coordinatesList objectAtIndex:0] floatValue]];
        }
    }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{      
    // XML document is completely parsed, dispatch an event for app to handle data as needed
   
    [[NSNotificationCenter defaultCenter] postNotificationName:@"mapDataParseComplete" object:nil];
    [mapsDataParser release]; mapsDataParser = nil;
}

- (void)dealloc
{
    [super dealloc];
   
    mapsDataParser.delegate = nil;
    [mapsDataParser release]; mapsDataParser = nil;
    [currentMapLocation release]; currentMapLocation = nil;
    [locationData release]; locationData = nil;
}

@end

Here’s the basic rundown of how the implementation works:

  1. Construct the Google Maps URL from passed data
  2. Create the NSXML
  3. Set it’s delegate to the MapDataParser class
  4. Load the XML from constructed string
  5. Step through the loaded data saving what we need in MapLocationVO objects.
  6. Dispatch event notifying app that the data is complete and ready for use

You can see that we always create a new MapLocationVO in the didStartElement delegate method if the element name is “Placemark”. You can see in the XML that “Placemark” is the wrapping element for a business listing. There is also some additional data in the XML we don’t care about, so we set the isPlacemark boolean to true.

If it is not a “Placemark” element, we store the value to check against in the foundCharacters delegate method. In this method, we are checking for the “title”, “Snippet”, and “coordinates” elements. When we encounter these elements we set them accordingly on the current MapLocationVO.

In the didEndElement delegate method, we set isPlacemark to false becuase have exited the wrapping “Placemark” element. We also add the MapLocationVO to our data array and do some clean up.

After we have gathered all our map data the parser reaches the end of the document and fires the parserDidEndDocument method. Here dispatch the “mapDataParseComplete” event.

You can now use the collected data however you need. In part 2 of this series we’ll take a look at how to use CoreLocation to find the user’s location and get the data based on the coordinates. Then, in part 3 we’ll tie it all together by displaying the business listings in a map view with custom markers.

SOURCE FILES

http://www.zen-sign.com/finding-business-listings-and-displaying-with-mapkit-part-1/


推荐阅读
  • This article explores the process of integrating Promises into Ext Ajax calls for a more functional programming approach, along with detailed steps on testing these asynchronous operations. ... [详细]
  • 我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • Jupyter Notebook多语言环境搭建指南
    本文详细介绍了如何在Linux环境下为Jupyter Notebook配置Python、Python3、R及Go四种编程语言的环境,包括必要的软件安装和配置步骤。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • 1,滤波流程2,图像的金字塔分解(拉普拉斯金字塔)3,金字塔傅里叶频率组合滤波(本文完ÿ ... [详细]
  • 本文探讨了如何选择一个合适的序列化版本ID(serialVersionUID),包括使用生成器还是简单的整数,以及在不同情况下应如何处理序列化版本ID。 ... [详细]
  • 本文旨在探讨Swift中的Closure与Objective-C中的Block之间的区别与联系,通过定义、使用方式以及外部变量捕获等方面的比较,帮助开发者更好地理解这两种机制的特点及应用场景。 ... [详细]
  • 本文分享了作者在使用LaTeX过程中的几点心得,涵盖了从文档编辑、代码高亮、图形绘制到3D模型展示等多个方面的内容。适合希望深入了解LaTeX高级功能的用户。 ... [详细]
  • WebBenchmark:强大的Web API性能测试工具
    本文介绍了一款名为WebBenchmark的Web API性能测试工具,该工具不仅支持HTTP和HTTPS服务的测试,还提供了丰富的功能来帮助开发者进行高效的性能评估。 ... [详细]
  • 本文详细介绍了Android系统的四层架构,包括应用程序层、应用框架层、库与Android运行时层以及Linux内核层,并提供了如何关闭Android系统的步骤。 ... [详细]
author-avatar
冰月雪镜樱1993
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有