65.9K
CodeProject 正在变化。 阅读更多。
Home

在 iPhone 应用程序中消费 RESTful 服务 (bit.ly)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (5投票s)

2009年8月19日

Ms-PL

6分钟阅读

viewsIcon

56990

如何在 iPhone 应用程序中消费 RESTful 服务 (bit.ly)

引言

近来,由于 iPhone 的巨大成功,许多为 Windows/Linux 开发的程序员已经转向了 iPhone。在苹果应用商店最成功的应用中,首先是游戏。其次是像 Tweetie 这样消费 Web 服务(REST 或其他)的应用。如果你不是游戏程序员,开始开发游戏是相当困难的。然而,开发消费 Web 服务的 iPhone 应用程序则相当容易。在本文中,我将演示如何编写一个消费 Web 服务的 iPhone 应用程序。我将以 bit.ly 的 REST 服务为例,在文章末尾,我们将开发一个不错的 Objective-C 版 “bit.ly” 封装库。对于不熟悉 REST 的读者,它代表表述性状态转移(Representational State Transfer)。请前往维基百科的这个页面了解更多详情。本文分为两部分,第一部分关注 XML,第二部分关注 JSON。在第二部分末尾,你可以下载附带的源代码。

Bit.ly 文档

众所周知,Bit.ly 是一个 URL 缩短服务。当 Twitter 开始使用 bit.ly 作为其默认的 URL 缩短服务,取代 tinyurl.com 后,它突然间变得流行起来。bit.ly 的 REST 文档可以在 Google Code 的这个页面找到。

在动手写真正的代码之前的一些基础知识

认证类型

bit.ly(以及许多类似的服务)使用一种称为“基本认证”的 HTTP 认证方式。在基本认证中,客户端输入的用户名和密码会用一个 : 连接起来,然后将得到的字符串转换为 “base64” 编码。这个字符串会随着 HTTP 请求头一起传递,通常在每次需要登录才能执行的 API 调用中都会发送。还有一种认证类型是 oAuth,即开放认证(Open Authentication)。目前,bit.ly 尚未使用 oAuth。解释 oAuth 本身就需要一整篇文章,超出了本文的范围。

HTTP 请求类型

当你访问一个 RESTful 服务时,你要么是请求数据,要么是提交数据。在大多数情况下,你的 HTTP 请求类型是“GET”或“POST”。还有两种请求类型,即“PUT”和“DELETE”。何时使用哪种类型取决于 RESTful 服务的设计者。作为消费者,你只需遵循文档即可。在我们的例子中,bit.ly 只会使用“GET”方法。

真正的代码

你可能会感到惊讶,访问一个 RESTful 服务以获取数据,其实只需要 10 行代码。

NSString *longURL = @"http://mugunthkumar.com"
NSString *baseURLString =
    @"http://api.bit.ly/shorten?version=2.0.1&" + 
    @"longUrl=%@&login=bitlyapidemo&apiKey=yourapikeyhere";
NSString *urlString = [[NSString alloc] initWithFormat:@"%@%@",
baseURLString, longURL];
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSString *result = [[NSString alloc] initWithContentsOfURL:url];yourapikeyhere

查看结果

NSLog(result);

结果

[url release];
[urlString release];
[result release];

解析结果

我们用“NSLogged”输出的结果可以是 XML 或 JSON 格式。在我们的例子中,bit.ly 默认发送的是 JSON 格式的数据,这也是目前最常用的格式。对于传输相同量的数据,JSON 比 XML 更轻量。关于哪种格式更适合数据传输,一直存在很多争论。我个人更喜欢 JSON。近来,随着 JSON 解析器的出现,JSON 正在逐渐超越 XML。Objective C 有一个非常强大的 JSON 解析器,叫做 json-framework。我们将在本文的下一部分讨论它。另一种数据格式,即 XML,只有当你在 URL 中传递

format=xml

作为附加参数时,bit.ly 才会返回。对于解析 XML,有两个解析器。一个是 NSXMLParser,另一个是更快的 libxml2。虽然 libxml2 更快,但只有在你需要解析超过 10 MB 的 XML 数据时,才建议在你的 iPhone 应用中使用它。当你的 XML 数据很小(就像我们的情况),NSXMLParserlibxml2 之间的性能差距非常微小。就 bit.ly 而言,缩短网址的 API 返回的数据小于 1 KB。大多数 RESTful 服务返回的数据量都非常小(通常在几百 KB 级别)。我更喜欢 NSXMLParser 的一个原因是,你的代码会比使用 libxml2 时更整洁。在本文中,我将带你了解这两种处理数据的方式。

解析XML

[parser initWithContentsOfURL: url];
[parser setDelegate:self];

[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];

[parser parse];
[parser release];

使用 NSXMLParser 解析 XML 数据再简单不过了。你只需创建一个 NSXMLParser 类型的对象(解析器),初始化它,然后调用 parse 方法。

注意事项

然而,有几点需要注意。

  1. 你可以用 NSURLNSData 来初始化解析器对象。两种方法效果一样好。
  2. 必须将代理(delegate)设置为 self。否则,NSXMLParser 无法通知你相关事件。
  3. 接下来的三行是可选的。如果你想收到这些事件的通知,通常将它们设置为 YES
  4. [parser parse] 的调用是阻塞式的。这意味着,在整个内容解析完成之前,它不会返回。因此,你可以在下一行释放任何相关的内存。

来自 NSXMLParser 的回调

NSXMLParser 大约有 14 个回调方法。但通常你只需实现其中的三个就足够了。它们是:

parser:didStartElement:namespaceURI:qualifiedName:attributes:
parser:didEndElement:namespaceURI:qualifiedName:
parser:foundCharacters:

XMLParser 遇到一个 XML 开始标签时,didStartElement 方法会被调用。你通常在这个函数中初始化临时变量并读取属性(如果有的话)。在 bit.ly 的例子中,你只需要读取“shortUrl”元素。只处理这一个元素就够了。

ShortURL from bit.ly

来自 bit.ly 的 ShortURL

声明以下变量:NSStrings 类型的 currentShortURLactualShortURLcurrentElement。将以下代码写入 didStartElement 代码块中:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
     namespaceURI:(NSString *)namespaceURI qualifiedName:
     (NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = [[elementName copy] autorelease];
if ([elementName isEqualToString:@"shortUrl"]) {
        currentShortURLString = [[NSString alloc] init];
}

现在,在 foundCharacters 代码块中,写入以下代码:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:@"shortURL"]) {
        [currentShortURLString appendString:string];
}

didEndElement 代码块中,写入:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
            namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"shortURL"]) {

    actualURLString = currentURLString;
}

现在,当解析结束时,在 [parser release] 函数之后,actualShortURLString 将包含缩短后的 URL。

到此为止。如果你没能跟上这篇博文中的代码,你随时可以下载附带的源代码(在下一部分中)。要获取有关使用 NSXMLParser 进行解析的更详细信息,请阅读这篇文章

解析 JSON

解析 JSON 比解析 XML 简单得多。事实上,我甚至不愿称之为“解析”,因为你根本不需要编写解析器!!!通过使用适用于 iPhone 的开源 json-framework 工具包,你可以轻松地将一个 JSON 字符串“转换”成一个 NSDictionary。现在我们来看看代码。

JSON 解析代码

JSON 解析远比 XML 简单。实际上,下面附带的代码使用的就是 JSON。

解析 bitly 信息就像写这三行代码一样简单:

SBJSON *jsonParser = [SBJSON new];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *dict = (NSDictionary*)[jsonParser objectWithString:jsonString];

返回的字符串是一个键值对的字典。要读取一个值,你可以调用 NSDictionary 中的 objectForKey 函数。

在大多数情况下,包括 bit.ly,JSON 返回的字符串总是包含嵌套在其中的其他字典。要读取一个字典中的值,只需像这样嵌套你的调用:

NSString *shortURL = [[[dict objectForKey:@"results"]
objectForKey:f_longURL]
objectForKey:@"shortUrl"];

源代码和文档

源代码
文档

只需三行代码,你就可以使用这个封装库来缩短你的 URL。

用你的登录名apikey 初始化这个辅助类。

bitlyHelper = [[MKBitlyHelper alloc] init];
[bitlyHelper initWithLoginName:@"yourlogin" andAPIKey:@"yourapi"];

在你的应用程序中,你可以提供特定于应用程序的 API,也可以提供用户提供的 API。登录 bit.ly API 有助于跟踪点击量和来源。这些类本身不提供登录名APIKey

现在,缩短或展开 URL 就像调用这些函数一样简单:

NSString *shortURL = [bitlyHelper shortenURL:@"http://mugunthkumar.com"];
NSString *longURL = [bitlyHelper expandURL:shortURL];

免责声明和其他废话...

请注意,代码中可能存在错误。正如高德纳(Donald Knuth)所说:

“请当心上面代码中的 bug;我只证明了它是正确的,但没有运行过它。”

欢迎随意使用和重新分发此代码。源代码的任何衍生作品都必须保留版权声明和我的署名。

你可以在你的应用程序中选择性地署名我,尽管这不是强制性的。如果你这么做,我会很高兴。;-)

相关文章

  1. iPhone 教程 – 应用内发送邮件
© . All rights reserved.