<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>iPhoneGeek 爱疯极客 &#187; 网络</title>
	<atom:link href="http://www.iphone-geek.cn/category/%e7%bc%96%e7%a8%8b/%e7%bd%91%e7%bb%9c/feed" rel="self" type="application/rss+xml" />
	<link>http://www.iphone-geek.cn</link>
	<description>iPhone 新闻，编程，技巧与提示，代码，教程</description>
	<lastBuildDate>Thu, 08 Dec 2011 01:18:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>iPhone上通过http传递JSON数据</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e4%b8%8a%e9%80%9a%e8%bf%87http%e4%bc%a0%e9%80%92json%e6%95%b0%e6%8d%ae</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e4%b8%8a%e9%80%9a%e8%bf%87http%e4%bc%a0%e9%80%92json%e6%95%b0%e6%8d%ae#comments</comments>
		<pubDate>Fri, 06 Aug 2010 09:03:49 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=1019</guid>
		<description><![CDATA[

本教程介绍了在iPhone程序中怎样访问JSON web service的详细步骤。


本教程创建了一个简单示例“幸运数字”，它有一个标签，其内容是通过建立于HTTP web service之上的JSON更新的。

源代码/Github

本教程的 源代码 存储于GitHub上。请运行下列命令获取代码：


打开终端程序，改变目录到你希望存储源代码的目录下
输入 git clone  git://github.com/dcgrigsby/luckynumbers.git 获取源代码




iPhone JSON 库

本教程使用了Stig Brautasetd的JSON library (version 2.2)，它提供了解析和生成JSON的功能。在本教程中没有使用生成JSON的功能。

此JSON库提供两种方法解析JSON：(1) 通过category对NSString进行扩展以实现JSON解析 (2) 较为底层一点的基于目标的解析器。本教程从简单方案开始，即方案(1)；在本教程介绍时将介绍方案(2)。


下载 磁盘映像



在稍后的步骤中我们将介绍磁盘映像的使用。

创建项目

启动Xcode 并创建一个新的 View-Based iPhone 程序，命名为  LuckyNumbers:


在Xcode菜单中使用 File &#62; New Project… 创建一个新项目
 在 iPhone OS &#62;  Application 中点取View-Based Application，按下Choose…
将此项目命名为 LuckyNumbers 并按下 Save



为此项目增添JSON支持

要使用JSON功能，我们需要将JSON库加入到项目中：


在项目的 Groups  &#38; Files 面板上展开 LuckyNumbers 项目。
使用Finder，找到你先前下载的 JSON_2.2.dmg 文件，双击加载磁盘映像。带有此DMG内容的另一个新的Finder窗口将打开
将此DMG内容中的 JSON 目录拖入到Xcode [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.mobileorchard.com/wp-content/uploads/2009/03/snap.png" alt="" /><br />
<br class="spacer_" /><br />
本教程介绍了在iPhone程序中怎样访问JSON web service的详细步骤。<br />
<br class="spacer_" /><br />
<span id="more-1019"></span><br />
本教程创建了一个简单示例“幸运数字”，它有一个标签，其内容是通过建立于HTTP web service之上的JSON更新的。<br />
<br class="spacer_" /></p>
<h3>源代码/Github</h3>
<p><br class="spacer_" /><br />
本教程的 <a href="http://github.com/dcgrigsby/luckynumbers">源代码</a> 存储于GitHub上。请运行下列命令获取代码：</p>
<blockquote>
<ol style="font-size: 90%;">
<li>打开终端程序，改变目录到你希望存储源代码的目录下</li>
<li>输入 <em>git clone  git://github.com/dcgrigsby/luckynumbers.git </em>获取源代码<em><br />
</em></li>
</ol>
</blockquote>
<p><br class="spacer_" /></p>
<h3>iPhone JSON 库</h3>
<p><br class="spacer_" /><br />
本教程使用了Stig Brautasetd的<a href="http://code.google.com/p/json-framework/">JSON library</a> (version 2.2)，它提供了解析和生成JSON的功能。在本教程中没有使用生成JSON的功能。<br />
<br class="spacer_" /><br />
此JSON库提供两种方法解析JSON：(1) 通过category对NSString进行扩展以实现JSON解析 (2) 较为底层一点的基于目标的解析器。本教程从简单方案开始，即方案(1)；在本教程介绍时将介绍方案(2)。</p>
<blockquote>
<ol style="font-size: 90%;">
<li><a href="http://code.google.com/p/json-framework/downloads/list">下载</a> 磁盘映像</li>
</ol>
</blockquote>
<p><br class="spacer_" /><br />
在稍后的步骤中我们将介绍磁盘映像的使用。<br />
<br class="spacer_" /></p>
<h3>创建项目</h3>
<p><br class="spacer_" /><br />
启动Xcode 并创建一个新的 View-Based iPhone 程序，命名为  LuckyNumbers:</p>
<blockquote>
<ol style="font-size: 90%;">
<li>在Xcode菜单中使用 <em>File &gt; New Project…</em> 创建一个新项目</li>
<li><em> </em>在 <em>iPhone OS &gt;  Application</em> 中点取<em>View-Based Application，</em>按下<em>Choose…</em></li>
<li>将此项目命名为 <em>LuckyNumbers</em> 并按下 <em>Save</em></li>
</ol>
</blockquote>
<p><br class="spacer_" /></p>
<h3>为此项目增添JSON支持</h3>
<p><br class="spacer_" /><br />
要使用JSON功能，我们需要将JSON库加入到项目中：</p>
<blockquote>
<ol style="font-size: 90%;">
<li>在项目的<em> Groups  &amp; Files</em> 面板上展开 <em>LuckyNumbers</em> 项目。</li>
<li>使用Finder，找到你先前下载的 <em>JSON_2.2.dmg</em> 文件，双击加载磁盘映像。带有此DMG内容的另一个新的Finder窗口将打开</li>
<li>将此DMG内容中的 <em>JSON</em> 目录拖入到Xcode <em>Groups  &amp; Files </em>面板中<em>LuckyNumbers</em> 项目图标下的<em>Classes</em> 文件夹中</li>
</ol>
</blockquote>
<p><br class="spacer_" /><br />
为测试JSON库是否正确设置，我们将解析一个JSON字典字符串，并在console中输出其结果NSDictionary。此功能是在<em>viewDidLoad</em>中完成。<br />
<br class="spacer_" /><br />
在 LuckyNumbersViewController.m 中加入如下代码：</p>
<pre>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#import &quot;LuckyNumbersViewController.h&quot;<br />
#import &quot;JSON/JSON.h&quot;<br />
<br />
@implementation LuckyNumbersViewController<br />
<br />
- (void)viewDidLoad {<br />
&nbsp; &nbsp; [super viewDidLoad];<br />
&nbsp; &nbsp; NSString *jsonString = [NSString stringWithString:@&quot;{\&quot;foo\&quot;: \&quot;bar\&quot;}&quot;];<br />
&nbsp; &nbsp; NSDictionary *dictionary = [jsonString JSONValue];<br />
&nbsp; &nbsp; NSLog(@&quot;Dictionary value for \&quot;foo\&quot; is \&quot;%@\&quot;&quot;, [dictionary objectForKey:@&quot;foo&quot;]);<br />
}<br />
<br />
- (void)dealloc {<br />
&nbsp; &nbsp; [super dealloc];<br />
}<br />
<br />
@end</div></td></tr></tbody></table></div>
</pre>
<p><br class="spacer_" /><br />
运行项目。如果 JSON SDK 设置正确的话，你应该将在console中见到如下信息：“ <em>Dictionary value  for “foo” is “bar” ”</em>.<br />
<br class="spacer_" /></p>
<h3>简单UI设置</h3>
<p><br class="spacer_" /><br />
我们最终成品是使用 UILabel 来显示通过HTTP 和 JSON 获取的幸运数字。<br />
<br class="spacer_" /><br />
在 LuckyNumbersViewController.h 使用如下代码：</p>
<pre>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#import &lt;UIKit/UIKit.h&gt;<br />
<br />
@interface LuckyNumbersViewController : UIViewController {<br />
&nbsp; &nbsp; IBOutlet UILabel *label;<br />
}<br />
<br />
@end</div></td></tr></tbody></table></div>
</pre>
<p><br class="spacer_" /><br />
<em>IBOutlet</em> 是一个宏，它通知编译器将变量与通过Interface Builder 的WYSIWYG添加的UILabel元件联系起来。下一步我们将添加元件并将这两部分连接起来。<br />
<br class="spacer_" /><br />
在Interface Builder中编辑 LuckyNumbersViewController.xib 文件：</p>
<blockquote>
<ol style="font-size: 90%;">
<li>在<em>Groups &amp; Files</em>中展开<em>LuckyNumbers</em>下的 <em>Resources</em> 文件夹。</li>
<li>双击 <em>LuckyNumbersViewController.xib</em> 文件。</li>
</ol>
</blockquote>
<p><br class="spacer_" /><br />
确保 Library, Inspector 和 View 窗口都打开/可见。如果没有的话：</p>
<blockquote>
<ol style="font-size: 90%;">
<li>在菜单中使用 <em>Tools &gt; Library</em> 显示 Library 窗口</li>
<li>在菜单中使用 <em>Tools &gt; Inspector</em> 显示 Inspector 窗口</li>
<li>在 <em>LuckyNumbersViewController.xib</em> 窗口中点击 View 图标</li>
</ol>
</blockquote>
<p><br class="spacer_" /><br />
添加一个label:</p>
<blockquote>
<ol style="font-size: 90%;">
<li>在<em>Library </em>窗口中找到 <em>Label</em> 元件并拖入view</li>
<li>在 <em>View </em>窗口中将 label 放大到整个view的一半</li>
<li>在 <em>Inspector </em> 窗口中的 <em>View Attributes</em>下 , 将 label 的行数设为0。</li>
</ol>
</blockquote>
<p><br class="spacer_" /><br />
将 label 行数设为0表示lable的尺寸在其指定的边界内动态可变。<br />
<br class="spacer_" /><br />
连接 Interface Builder 中的 label 到代码 <em>label</em>。   仍然在 Interface Builder 中:</p>
<blockquote>
<ol style="font-size: 90%;">
<li>Control + 点击<em>LuckyNumbersViewController.xib</em> 窗口中的 <em>File’s Owner</em> 图标</li>
<li>在弹出菜单中，点击并按住<em>Outlets</em> 部分 lable 行右方的圆圈</li>
<li>拖动鼠标到View中的 <em>Label</em> 上。 将出现一条蓝线连接这两个部分。</li>
</ol>
</blockquote>
<p><br class="spacer_" /><br />
这两个部分连接后，弹出菜单将如图所示。<br />
<br class="spacer_" /><br />
<img src="http://www.mobileorchard.com/wp-content/uploads/2009/03/connection.png" alt="" /><br />
<br class="spacer_" /><br />
如果一切正常的话，保存并关闭Interface  Builder。<br />
<br class="spacer_" /></p>
<h3>通过HTTP获取 JSON 数据</h3>
<p><br class="spacer_" /><br />
我们将使用 Cocoa 中的 NSURLConnection 来发送一个 HTTP 请求从而获取 JSON 数据。<br />
<br class="spacer_" /><br />
Cocoa 在进行HTTP请求时有两种选项：同步和异步。同步请求中程序的主runloop中运行，使得在请求的过程中，程序停止运行。而异步请求使用回调来避免程序锁住而且简单易用。因此我们使用异步请求。<br />
<br class="spacer_" /><br />
首先我们需要修改视图控制器接口，创建一个<em>NSMutableData</em>变量来保存响应数据。我们在接口（.h）中而不是在方法中定义此变量是因为响应数据是逐步的而不是一次性返回的，我们需要将所有数据组合在一起。<br />
<br class="spacer_" /><br />
修改 LuckNumbersViewController.h。改变如下黑体所示：</p>
<pre>#import &lt;UIKit/UIKit.h&gt;

@interface LuckyNumbersViewController : UIViewController {
	IBOutlet UILabel *label;
	<strong>NSMutableData *responseData;</strong>
}</pre>
<p><br class="spacer_" /><br />
简单起见，我们在 <em>viewDidLoad</em>中进行HTTP请求。<br />
<br class="spacer_" /><br />
修改 LuckyNumbersViewController.m :</p>
<pre>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#import &quot;LuckyNumbersViewController.h&quot;<br />
#import &quot;JSON/JSON.h&quot;<br />
<br />
@implementation LuckyNumbersViewController<br />
<br />
- (void)viewDidLoad {<br />
&nbsp; &nbsp; [super viewDidLoad];<br />
<br />
&nbsp; &nbsp; responseData = [[NSMutableData data] retain];<br />
&nbsp; &nbsp; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@&quot;http://www.unpossible.com/misc/lucky_numbers.json&quot;]];<br />
&nbsp; &nbsp; [[NSURLConnection alloc] initWithRequest:request delegate:self];<br />
}<br />
<br />
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {<br />
&nbsp; &nbsp; [responseData setLength:0];<br />
}<br />
<br />
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {<br />
&nbsp; &nbsp; [responseData appendData:data];<br />
}<br />
<br />
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {<br />
&nbsp; &nbsp; label.text = [NSString stringWithFormat:@&quot;Connection failed: %@&quot;, [error description]];<br />
}<br />
<br />
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {<br />
&nbsp; &nbsp; [connection release];<br />
}<br />
<br />
- (void)dealloc {<br />
&nbsp; &nbsp; [super dealloc];<br />
}<br />
<br />
@end</div></td></tr></tbody></table></div>
</pre>
<p><br class="spacer_" /><br />
responseData 变量用来存放数据，然后在  viewDidload中进行HTTP连接;  <em>didReceiveData</em>用来收集返回的数据; 空白的 connectionDidFinishLoading 表示数据响应结束。<br />
<br class="spacer_" /></p>
<h3>使用 JSON 数据</h3>
<p><br class="spacer_" /><br />
下面我们将展示怎样在 connectionDidFinishLoading 中对获取的 JSON 数据的进行处理。<br />
<br class="spacer_" /><br />
修改LuckyNumbersViewController.m中的 connectionDidFinishLoading 方法。使用下面代码：</p>
<pre>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">- (void)connectionDidFinishLoading:(NSURLConnection *)connection {<br />
&nbsp; &nbsp; [connection release];<br />
<br />
&nbsp; &nbsp; NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];<br />
&nbsp; &nbsp; [responseData release];<br />
<br />
&nbsp; &nbsp; NSArray *luckyNumbers = [responseString JSONValue];<br />
<br />
&nbsp; &nbsp; NSMutableString *text = [NSMutableString stringWithString:@&quot;Lucky numbers:\n&quot;];<br />
<br />
&nbsp; &nbsp; for (int i = 0; i &amp;lt; [luckyNumbers count]; i++)<br />
&nbsp; &nbsp; &nbsp; &nbsp; [text appendFormat:@&quot;%@\n&quot;, [luckyNumbers objectAtIndex:i]];<br />
<br />
&nbsp; &nbsp; label.text = &nbsp;text;<br />
}</div></td></tr></tbody></table></div>
</pre>
<p><br class="spacer_" /><br />
本文最开始的示例代码中使用了 NSDictionary。而现在我们使用 NSArray。 解析器非常灵活，其返回对象 &#8211; 包括嵌套对象 &#8211; 将 JSON数据类型与Objective-C的数据类型很好地匹配起来。<br />
<br class="spacer_" /></p>
<h3>更好的错误处理</h3>
<p><br class="spacer_" /><br />
至此我们使用了NSString扩展的方法对JSON数据进行了解析。这样做是非常简单的。<br />
<br class="spacer_" /><br />
但不幸的是，使用此方法是错误处理变得很困难。如果JSON解析器因为某种原因失败的话，它仅仅返回一个nil值。但是如果错误发生时你观察console，你就会发现一些信息描述了引擎解析器失败的原因。<br />
<br class="spacer_" /><br />
如果我们能将详细错误信息传递给用户，那将更加用户友好。要达到这个目的，我们将切换到JSON SDK支持的第二种面向对象的方法。<br />
<br class="spacer_" /><br />
修改LuckyNumbersViewController.m中<em>connectionDidFinishLoading</em> 方法。使用下面代码：</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">- (void)connectionDidFinishLoading:(NSURLConnection *)connection {<br />
&nbsp; &nbsp; [connection release];<br />
<br />
&nbsp; &nbsp; NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];<br />
&nbsp; &nbsp; [responseData release];<br />
<br />
&nbsp; &nbsp; NSError *error;<br />
&nbsp; &nbsp; SBJSON *json = [[SBJSON new] autorelease];<br />
&nbsp; &nbsp; NSArray *luckyNumbers = [json objectWithString:responseString error:&amp;error];<br />
&nbsp; &nbsp; [responseString release]; &nbsp; <br />
<br />
&nbsp; &nbsp; if (luckyNumbers == nil)<br />
&nbsp; &nbsp; &nbsp; &nbsp; label.text = [NSString stringWithFormat:@&quot;JSON parsing failed: %@&quot;, [error localizedDescription]];<br />
&nbsp; &nbsp; else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; NSMutableString *text = [NSMutableString stringWithString:@&quot;Lucky numbers:\n&quot;];<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i &lt;; [luckyNumbers count]; i++)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [text appendFormat:@&quot;%@\n&quot;, [luckyNumbers objectAtIndex:i]];<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; label.text = &nbsp;text;<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
</pre>
<p><br class="spacer_" /><br />
使用此方法可以帮助我们在JSON解析器发生错误时指出错误所在以便进行更好的错误处理。<br />
<br class="spacer_" /></p>
<h3>结论</h3>
<p><br class="spacer_" /><br />
JSON SDK 和 Cocoa 固有的 HTTP功能使得在iPhone应用程序中运用JSON web service变得非常容易。<br />
<br class="spacer_" /><br />
原文见：<a href="http://www.mobileorchard.com/tutorial-json-over-http-on-the-iphone/">Tutorial: JSON Over HTTP On The iPhone</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e4%b8%8a%e9%80%9a%e8%bf%87http%e4%bc%a0%e9%80%92json%e6%95%b0%e6%8d%ae/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>创建离线iPhone Web App</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e5%88%9b%e5%bb%ba%e7%a6%bb%e7%ba%bfiphone-web-app</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e5%88%9b%e5%bb%ba%e7%a6%bb%e7%ba%bfiphone-web-app#comments</comments>
		<pubDate>Tue, 18 May 2010 05:09:21 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[Web App]]></category>
		<category><![CDATA[教程]]></category>
		<category><![CDATA[浏览器]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=952</guid>
		<description><![CDATA[创建Web App的好处很多，比如：


可以运行在任何平台上 （当然要考虑浏览器的兼容性和屏幕大小问题） 
不需要学习iPhone编程语言 
最大的好处是不需要经过App Store批准 


随着Internet技术的迅速发展，使得Web App越来越强大，从简单的应用甚至到游戏，都可能通过Web App实现。但是，它要求随时连接到Internet，大大降低了Web App的实用性。随着Safari对HTML 5的支持，使得Web App的离线运行成为可能。这意味着你可以在没有Internet连接的情况下运行你的应用程序。

下面的例子改编自How to Make an HTML5 iPhone App，它介绍了创建一个离线“积木”游戏的全过程，我加上了创建用户自定义的桌面图标和启动画面的方法，使它看上去完全像一个真正的iPhone应用程序，而这是完全不需要通过Apple的App Store批准的。


基本要求

网页编程技术：HTML(5)， CSS 以及 JavaScript。

准备工作

由于我们要利用HTML5的离线缓存技术，我们需要访问网页服务器以便对文件的HTTP Headers进行修改（稍后我们会详细讨论）。

Apache服务器很容易通过修改 .htaccess 文件完成你需要的工作。这里是一篇教程关于 m使用htaccess修改HTTP header。

然后你需要打开Safari浏览器的调试窗以帮助你进行调试。在Settings > Safari > Developer中打开调试终端，它能够帮助你发现一些潜在的Javascript错误。记住在完成调试后，关闭调试窗。



应用程序缓存

HTML5 有关离线的标准参考这里。

应用程序缓存允许浏览器预先确定网页所需的所有文件，然后它将保存这些文件。格式是绝对地址如http://yourwebserver.com/picture.png 或者相对地址(/picture.png)，浏览器将离线保存这些文件。

你还可以列出不需要缓存的URL。最主要的部分是清单文件（需要离线缓存文件的清单）在Http Header中的filetype必须设置为text/manifest。


屏幕尺寸

在设计iPhone Web App时必须注意，当处于app模式时，屏幕尺寸为 320px X 460px，而在web模式时为 320px X 356px。这也许会影响你的用户界面设计。




代码

12345678910111213141516&#60;!DOCTYPE html&#62;
&#60;html manifest=&#34;tetris.manifest&#34;&#62;
&#60;head&#62;
&#160; &#160; &#60;meta name=&#34;viewport&#34; content=&#34;user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0&#34;/&#62;
&#160; &#160; &#60;meta name=&#34;apple-mobile-web-app-capable&#34; content=&#34;yes&#34; [...]]]></description>
			<content:encoded><![CDATA[<p>创建Web App的好处很多，比如：</p>
<p><br class="spacer_" /></p>
<ul>
<li>可以运行在任何平台上 （当然要考虑浏览器的兼容性和屏幕大小问题） </li>
<li>不需要学习iPhone编程语言 </li>
<li>最大的好处是不需要经过App Store批准 </li>
</ul>
<p><br class="spacer_" /></p>
<p>随着Internet技术的迅速发展，使得Web App越来越强大，从简单的应用甚至到游戏，都可能通过Web App实现。但是，它要求随时连接到Internet，大大降低了Web App的实用性。随着Safari对HTML 5的支持，使得Web App的离线运行成为可能。这意味着你可以在没有Internet连接的情况下运行你的应用程序。</p>
<p><br class="spacer_" /></p>
<p>下面的例子改编自<a href="http://sixrevisions.com/web-development/html5-iphone-app/">How to Make an HTML5 iPhone App</a>，它介绍了创建一个离线“积木”游戏的全过程，我加上了创建用户自定义的桌面图标和启动画面的方法，使它看上去完全像一个真正的iPhone应用程序，而这是完全不需要通过Apple的App Store批准的。</p>
<p><span id="more-952"></span></p>
<p><br class="spacer_" /></p>
<h3>基本要求</h3>
<p><br class="spacer_" /></p>
<p>网页编程技术：HTML(5)， CSS 以及 JavaScript。</p>
<p><br class="spacer_" /></p>
<h3>准备工作</h3>
<p><br class="spacer_" /></p>
<p>由于我们要利用HTML5的离线缓存技术，我们需要访问网页服务器以便对文件的<a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers">HTTP Headers</a>进行修改（稍后我们会详细讨论）。</p>
<p><br class="spacer_" /></p>
<p>Apache服务器很容易通过修改 .htaccess 文件完成你需要的工作。这里是一篇教程关于 <a href="http://www.askapache.com/htaccess/using-http-headers-with-htaccess.html">m使用htaccess修改HTTP header</a>。</p>
<p><br class="spacer_" /></p>
<p>然后你需要打开Safari浏览器的调试窗以帮助你进行调试。在Settings > Safari > Developer中打开调试终端，它能够帮助你发现一些潜在的Javascript错误。记住在完成调试后，关闭调试窗。</p>
<p><br class="spacer_" /></p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://www.iphone-geek.cn/wp-content/uploads/2010/05/image3.png" border="0" alt="image" width="324" height="484" /></p>
<p><br class="spacer_" /></p>
<h3>应用程序缓存</h3>
<p><br class="spacer_" /></p>
<p>HTML5 有关离线的标准参考这里。</p>
<p><br class="spacer_" /></p>
<p>应用程序缓存允许浏览器预先确定网页所需的所有文件，然后它将保存这些文件。格式是绝对地址如<a href="http://yourwebserver.com/picture.png">http://yourwebserver.com/picture.png</a> 或者相对地址(/picture.png)，浏览器将离线保存这些文件。</p>
<p><br class="spacer_" /></p>
<p>你还可以列出不需要缓存的URL。最主要的部分是清单文件（需要离线缓存文件的清单）在Http Header中的filetype必须设置为text/manifest。</p>
<p><br class="spacer_" /></p>
<p><br class="spacer_" /></p>
<h3>屏幕尺寸</h3>
<p><br class="spacer_" /></p>
<p>在设计iPhone Web App时必须注意，当处于app模式时，屏幕尺寸为 320px X 460px，而在web模式时为 320px X 356px。这也许会影响你的用户界面设计。</p>
<p><br class="spacer_" /></p>
<p><a href="http://www.iphone-geek.cn/wp-content/uploads/2010/05/image4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://www.iphone-geek.cn/wp-content/uploads/2010/05/image_thumb.png" border="0" alt="image" width="554" height="417" /></a></p>
<p><br class="spacer_" /></p>
<h3></h3>
<h3>代码</h3>
<p><br class="spacer_" /></p>
<div class="codecolorer-container html4strict mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE html&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a> manifest<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;tetris.manifest&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/meta.html"><span style="color: #000000; font-weight: bold;">meta</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;viewport&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0&quot;</span><span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/meta.html"><span style="color: #000000; font-weight: bold;">meta</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;apple-mobile-web-app-capable&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;yes&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/meta.html"><span style="color: #000000; font-weight: bold;">meta</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;apple-mobile-web-app-status-bar-style&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;black&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;apple-touch-icon&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;iphon_tetris_icon.png&quot;</span><span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;apple-touch-startup-image&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;startup.png&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;tetris.css&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">media</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;screen, mobile&quot;</span> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;main&quot;</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span>offline Tetris<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #808080; font-style: italic;">&lt;!-- Put your Markup Here --&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;tetris.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></div></td></tr></tbody></table></div>
<p><html>中的 manifest=&#8221;cache.manifest&#8221; 属性将告诉浏览器我们可能需要对文件进行离线缓存。</p>
<p><br class="spacer_" /></p>
<p>下面是Apple专用的HTML 5属性：</p>
<ul>
<li>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">apple-mobile-web-app-capable</div></td></tr></tbody></table></div>
<p>: 设置为离线模式 </li>
<li>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">apple-mobile-web-app-status-bar-style</div></td></tr></tbody></table></div>
<p>: 当处于离线时隐藏状态条，导航条 </li>
<li>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">apple-touch-icon</div></td></tr></tbody></table></div>
<p>:指向作为图标的图像 </li>
<li>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">apple-touch-startup-image</div></td></tr></tbody></table></div>
<p>: 指向作为启动图像的url</li>
</ul>
<p><br class="spacer_" /></p>
<h3>CSS</h3>
<p><br class="spacer_" /></p>
<p>这几乎与普通网页完全一样。还有一些webkit专用的CSS能实现一些特殊效果如动画等。</p>
<p><br class="spacer_" /></p>
<p>我们使用的CSS如下：</p>
<pre>body {
    overflow:hidden;
    background: #d7d7d7;
    margin:0;
    padding:0;
}
#tetris {
    width: 320px;
    height: 460px;
    background:#000;
}</pre>
<h3>JavaScript</h3>
<p><br class="spacer_" /></p>
<p>我使用的是 <a href="http://www.daltonridenhour.com">Dalton Ridenhour</a> 的Javascript，源代码在 <a href="http://github.com/daltonridenhour/DOM-Tetris">Github</a>。原JS是为普通网页设计的，我们仅需要修改一下拿掉对键盘的支持。</p>
<p><br class="spacer_" /></p>
<p>通常JS在iPhone上完全能正常工作，当然有一些例外。请参阅 <a href="http://www.quirksmode.org/blog/archives/2008/08/iphone_events.html">events on the iPhone</a> 。</p>
<p><br class="spacer_" /></p>
<p>下面是完成的网页，你可以进行测试，看看它是怎样离线运行的：</p>
<p><br class="spacer_" /></p>
<p><a href="http://tetris.alexkessinger.net">http://tetris.alexkessinger.net</a></p>
<p><br class="spacer_" /></p>
<h3>设定图标和启动画面</h3>
<p><br class="spacer_" /></p>
<p>使用iPhone Safari浏览器，很容易将应用程序的图标添加到你iPhone上的Home Screen。</p>
<p><br class="spacer_" /></p>
<ul>
<li>首先，创建一个57&#215;57的png图标。将其放在网站的文档根目录下（注意不是服务器的文档根目录）</li>
</ul>
<p><br class="spacer_" /></p>
<p><a href="http://www.iphone-geek.cn/wp-content/uploads/2010/05/image5.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" src="http://www.iphone-geek.cn/wp-content/uploads/2010/05/image_thumb1.png" border="0" alt="image" width="61" height="61" /></a></p>
<p><br class="spacer_" /></p>
<ul>
<li>在html中加入（见上面HTML代码部分） ，指向图标文件。</li>
<li>在html中加入（见上面HTML代码部分） ，指向启动画面图像文件。</li>
<li>打开浏览器，在地址栏输入你Web App的URL，按下浏览器下方的加号，选择“Add To Home Screen”,然后输入Web App的名称，比如Tetris。</li>
</ul>
<p><br class="spacer_" /></p>
<p>这样一个积木游戏的图标就添加到了你的iPhone屏幕上，启动后即使你的iPhone没有在线，也可以正常运行。</p>
<p><br class="spacer_" /></p>
<h3>我的设想</h3>
<p><br class="spacer_" /></p>
<p>这样的Web App看上去与普通程序没什么大区别，不过却需要用户自己添加图标，这虽然不是什么大问题，但还不是很完美。我想要是在你的网页上添加一项“安装到iPhone/iPod Touch/iPad”，在按下后可以自动添加图标，那么一切就完美了。我现在还没有解决方法，大家有什么建议吗？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e5%88%9b%e5%bb%ba%e7%a6%bb%e7%ba%bfiphone-web-app/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>怎样编写Apple Push Notification服务器</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%80%8e%e6%a0%b7%e7%bc%96%e5%86%99apple-push-notification%e6%9c%8d%e5%8a%a1%e5%99%a8</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%80%8e%e6%a0%b7%e7%bc%96%e5%86%99apple-push-notification%e6%9c%8d%e5%8a%a1%e5%99%a8#comments</comments>
		<pubDate>Fri, 29 Jan 2010 04:32:45 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[Push]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=417</guid>
		<description><![CDATA[


iPhone OS 3.0一个引入注目的新特性是push notifications（推送通知），它允许向已安装相关应用程序的各设备直接发送消息。苹果在新闻提示或IM应用中展示了此特性，它也十分完美地适合于我们的服务器监视服务程序Server Density。



我们的程序提供一个选项，当你设定的某个服务器事件发生时，通知会直接发送到你的iPhone上。这是非常有用的因为它提醒用户立即打开我们的程序查看引起此警示的服务器详情。

Apple提供了有关实现和处理设备上提示消息的  iPhone OS 的详细代码文档 ，但它只包括消息提供者服务器端编程指南。

作为消息提供者，我们需要与 Apple推送通知服务 (APNS)连接以发送消息到iPhone。为减少电池使用，一个设备仅需维持与APNS的一个连接。

本教程将从代码的层面介绍关于怎样建立一个推送通知服务器以连接APNS并使用推送通知到我们的服务器监视iPhone程序上。我们是使用PHP进行开发的，我们的示例都是PHP 5兼容的。
  
基本结构

使用唯一的SSL许可证连接到APNS

循环通过你需要发送到消息
为各消息构建有效载荷
断开与 APNS的连接

远程通知数据的流程是单向的。提供者将包括客户程序设备令牌和有效载荷的数据打包，发送到APNS，然后APNS再将通知发送给最终设备。


- Apple 文档

  
限制

有效载荷限制为256字节 &#8211; 它包括了消息主体以及你希望传送带其他属性。推送通知并不适于传送大量的数据。例如，我们仅仅传送一条短消息通知服务器监视的事件已经被触发了。
APNS并不提供消息发送成功与否的回馈状态。一个原因是如果一个设备无法联系那么发送给它的消息将被存于队列中，然而只有最新发送的消息被存于队列中 &#8211; 覆盖了先前发送但不成功的消息。
推送通知不适合用于发送紧急通知，因为消息仅在设备具有wifi或手机服务连接的情况下才能被发送，这也是为什么我们推荐与其它方法如email或SMS一起使用的原因。
用来与APNS通讯的SSL许可证（下面将讨论）是在程序层生成的。本教程涉及到实现方法仅适于单个iPhone程序，所以如果你有多个程序，那么你需要修改代码使之适合于使用多个许可证。

  
设备令牌

每条推送消息都必须针对某特定设备。这是通过使用在你的iPhone程序中由APNS产生的唯一deviceToken（设备令牌）来实现的。一旦获取了此令牌，你需要将其存储于服务器而不是你的iPhone程序内。它看上去像这样：
c9d4c07c fbbc26d6 ef87a44d 53e16983 1096a5d5 fd825475 56659ddd f715defc

在我们的 Server Density iPhone 程序中，我们在程序启动时调用相应的令牌生成方法，然后通过 HTTP API 调用 传回给我们的服务器 。这将使得deviceToken存储于服务器的有关用户的数据库中，从而我们可以使用它与持有此设备的用户进行通讯。
  
反馈服务

Apple 还提供了一个 反馈服务 ，你应该定期查询。它提供了一个以前使用过但不再有效的（例如用户卸载了你的iPhone程序）设备令牌列表。你可以从你的数据库中删除这些设备令牌。

本教程不涉及反馈服务的使用。
  
许可证

要进行推送服务的第一件事就是获取推送许可证。它用来对你通过SSL与APNS通讯进行识别。

在Mac上生成 Apple推送通知SSL许可证：

登录到 iPhone Developer Connection Portal 并点击 App IDs
创建一个不使用通配符的 App ID 。通配符 ID 不能用于推送通知服务。例如，我们的iPhone程序ID像这样：  AB123346CD.com.serverdensity.iphone
点击App ID旁的“Configure”，然后按下按钮生产 推送通知许可证。根据“向导”指导的步骤生成一个签名并上传，最后下载生成的许可证。此步骤在 Apple文档中 也有谈到。
通过双击.cer文件将你的 aps_developer_identity.cer 引入Keychain中。
在Mac上启动 Keychain助手，然后在login [...]]]></description>
			<content:encoded><![CDATA[<div><!--end meta--></div>
<div>
<div>
<p><a href="http://www.apple.com/iphone/softwareupdate/">iPhone OS 3.0</a>一个引入注目的新特性是<a href="http://developer.apple.com/iphone/program/sdk/apns.html">push notifications</a>（推送通知），它允许向已安装相关应用程序的各设备直接发送消息。苹果在新闻提示或IM应用中展示了此特性，它也十分完美地适合于我们的服务器监视服务程序<a href="http://www.serverdensity.com/">Server Density</a>。</p>
<p><br class="spacer_" /></p>
<p><a href="http://boxedice.files.wordpress.com/2009/07/sd-iphone-push-alert.png"><img title="Server monitoring iPhone application alert view" src="http://boxedice.files.wordpress.com/2009/07/sd-iphone-push-alert.png?w=200&amp;h=300" alt="Server monitoring iPhone application alert view" width="200" height="300" /></a></p>
<p><span id="more-417"></span></p>
<p>我们的程序提供一个选项，当你设定的某个服务器事件发生时，通知会直接发送到你的iPhone上。这是非常有用的因为它提醒用户立即打开我们的程序查看引起此警示的服务器详情。</p>
<p><br class="spacer_" /></p>
<p>Apple提供了有关实现和处理设备上提示消息的 <a href="http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html"> iPhone OS 的详细代码文档</a> ，但它只包括消息提供者服务器端编程指南。</p>
<p><br class="spacer_" /></p>
<p>作为消息提供者，我们需要与 Apple推送通知服务 (APNS)连接以发送消息到iPhone。为减少电池使用，一个设备仅需维持与APNS的一个连接。</p>
<p><br class="spacer_" /></p>
<p>本教程将从代码的层面介绍关于怎样建立一个推送通知服务器以连接APNS并使用推送通知到我们的服务器监视iPhone程序上。我们是使用PHP进行开发的，我们的示例都是PHP 5兼容的。</p>
<h3><strong> </strong> </h3>
<h3><strong>基本结构</strong></h3>
<p><br class="spacer_" /></p>
<p>使用唯一的SSL许可证连接到APNS</p>
<ol>
<li>循环通过你需要发送到消息</li>
<li>为各消息构建有效载荷</li>
<li>断开与 APNS的连接</li>
</ol>
<blockquote><p>远程通知数据的流程是单向的。提供者将包括客户程序设备令牌和有效载荷的数据打包，发送到APNS，然后APNS再将通知发送给最终设备。</p>
</blockquote>
<p><br class="spacer_" /></p>
<p>- <a href="http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html">Apple 文档</a></p>
<p><a href="http://boxedice.files.wordpress.com/2009/07/remote_notif_simple.jpg"><img title="APNS Flow" src="http://boxedice.files.wordpress.com/2009/07/remote_notif_simple.jpg?w=600&amp;h=82" alt="APNS Flow" width="600" height="82" /></a></p>
<h3><strong> </strong> </h3>
<h3><strong>限制</strong></h3>
<ul>
<li>有效载荷限制为256字节 &#8211; 它包括了消息主体以及你希望传送带其他属性。推送通知并不适于传送大量的数据。例如，我们仅仅传送一条短消息通知服务器监视的事件已经被触发了。</li>
<li>APNS并不提供消息发送成功与否的回馈状态。一个原因是如果一个设备无法联系那么发送给它的消息将被存于队列中，然而只有最新发送的消息被存于队列中 &#8211; 覆盖了先前发送但不成功的消息。</li>
<li>推送通知不适合用于发送紧急通知，因为消息仅在设备具有wifi或手机服务连接的情况下才能被发送，这也是为什么我们推荐与其它方法如email或SMS一起使用的原因。</li>
<li>用来与APNS通讯的SSL许可证（下面将讨论）是在程序层生成的。本教程涉及到实现方法仅适于单个iPhone程序，所以如果你有多个程序，那么你需要修改代码使之适合于使用多个许可证。</li>
</ul>
<h3><strong> </strong> </h3>
<h3><strong>设备令牌</strong></h3>
<p><br class="spacer_" /></p>
<p>每条推送消息都必须针对某特定设备。这是通过使用在你的iPhone程序中由APNS产生的唯一deviceToken（设备令牌）来实现的。一旦获取了此令牌，你需要将其存储于服务器而不是你的iPhone程序内。它看上去像这样：</p>
<p>c9d4c07c fbbc26d6 ef87a44d 53e16983 1096a5d5 fd825475 56659ddd f715defc</p>
<p><br class="spacer_" /></p>
<p>在我们的 Server Density iPhone 程序中，我们在程序启动时调用相应的令牌生成方法，然后通过 <a href="http://www.serverdensity.com/docs/api/functions/#iphone-setdevicetoken">HTTP API 调用</a> 传回给我们的服务器 。这将使得deviceToken存储于服务器的有关用户的数据库中，从而我们可以使用它与持有此设备的用户进行通讯。</p>
<h3><strong> </strong> </h3>
<h3><strong>反馈服务</strong></h3>
<p><br class="spacer_" /></p>
<p>Apple 还提供了一个 <a href="http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW3">反馈服务</a> ，你应该定期查询。它提供了一个以前使用过但不再有效的（例如用户卸载了你的iPhone程序）设备令牌列表。你可以从你的数据库中删除这些设备令牌。</p>
<p><br class="spacer_" /></p>
<p>本教程不涉及反馈服务的使用。</p>
<h3><strong> </strong> </h3>
<h3><strong>许可证</strong></h3>
<p><br class="spacer_" /></p>
<p>要进行推送服务的第一件事就是获取推送许可证。它用来对你通过SSL与APNS通讯进行识别。</p>
<p><br class="spacer_" /></p>
<p>在Mac上生成 Apple推送通知SSL许可证：</p>
<ol>
<li>登录到 <a href="http://developer.apple.com/iphone/manage/overview/index.action">iPhone Developer Connection Portal</a> 并点击 App IDs</li>
<li>创建一个不使用通配符的 App ID 。通配符 ID 不能用于推送通知服务。例如，我们的iPhone程序ID像这样：  AB123346CD.com.serverdensity.iphone</li>
<li>点击App ID旁的“Configure”，然后按下按钮生产 推送通知许可证。根据“向导”指导的步骤生成一个签名并上传，最后下载生成的许可证。此步骤在 <a href="http://developer.apple.com/iphone/prerelease/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ProvisioningDevelopment/ProvisioningDevelopment.html#//apple_ref/doc/uid/TP40008194-CH104-SW4">Apple文档中</a> 也有谈到。</li>
<li>通过双击.cer文件将你的 aps_developer_identity.cer 引入Keychain中。</li>
<li>在Mac上启动 Keychain助手，然后在login keychain中选择 Certificates分类。你将看到一个可扩展选项“Apple Development Push Services”</li>
<li>扩展此选项然后右击“Apple Development Push Services” > Export “Apple Development Push Services ID123”。保存为 apns-dev-cert.p12 文件。</li>
<li>扩展“Apple Development Push Services” 对“Private Key”做同样操作，保存为 apns-dev-key.p12 文件。</li>
<li>需要通过终端命令将这些文件转换为PEM格式：
<pre>openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12</pre>
</li>
<li>如果你想要移除密码，要么在导出/转换时不要设定或者执行：
<pre>openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem</pre>
</li>
<li>最后，你需要将键和许可文件合成为apns-dev.pem文件，此文件在连接到APNS时需要使用：
<pre>cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem</pre>
</li>
</ol>
<p><br class="spacer_" /></p>
<p>将此文件保存为一个易记的名字，你有可能以后会用到它。上述步骤同样适合于生成产品许可证。</p>
<h3><strong> </strong> </h3>
<h3><strong>载荷内容</strong></h3>
<p><br class="spacer_" /></p>
<p><a href="http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1">载荷</a> 格式化为遵循 RFC 4627标准的JSON格式。它由以下几部分组成：</p>
<ul>
<li>提示 &#8211; 显示于设备上的文本串</li>
<li>标识 &#8211; 设备屏幕中程序图标上显示的整数</li>
<li>声音 &#8211;  显示消息在设备的同时发出的声音的文本名字</li>
<li>本教程仅处理发送简单提示文本串，但也可以发送包括诸如显示自定义按钮等在内的各种选项的字典集。</li>
</ul>
<h3><strong> </strong> </h3>
<h3><strong>创建载荷</strong></h3>
<p><br class="spacer_" /></p>
<p>使用 PHP 很容易根据数组并 <a href="http://www.php.net/manual/en/function.json-encode.php">转换成 JSON</a>而创建载荷:</p>
<pre>$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);</pre>
<p><br class="spacer_" /></p>
<p>显示 $payload 的内容可以看到传送到<span style="font-family: Georgia;">APNS 的</span> JSON字符串：</p>
<pre>{
     "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" }
}</pre>
<p><br class="spacer_" /></p>
<p>这将使消息显示于设备上，触发提升声音并将“1”置于程序图标上。默认按钮“Close”和“View”同时会显示于弹出窗口上。</p>
<p><br class="spacer_" /></p>
<p>对于 Server Density iPhone程序而言，让用户按下“View”直接进入产生此提示的服务器是很重要的，所以我们增加了额外的自定义值：</p>
<pre>$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload['server'] = array('serverId' => $serverId, 'name' => $name);
$output = json_encode($payload);</pre>
<p><br class="spacer_" /></p>
<p>当用户按下“View”后，自定义server值将被传递到设备中的程序。JSON 值如下：</p>
<pre>{
     "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" },
     "server" : { "serverId" : 1, "name" : "Server name")
}</pre>
<p><br class="spacer_" /></p>
<p>256字节的限制适用于整个载荷，包括自定义字典集。</p>
<h3><strong> </strong> </h3>
<h3><strong>原生接口</strong></h3>
<p><br class="spacer_" /></p>
<p>在Server Density中，一旦产生了一条提示，将建立一个载荷并插入队列中。因此有必要时我们可以同时发送多个载荷。</p>
<p><br class="spacer_" /></p>
<p>Apple推荐使用这种方法，因为如果你在发送各载荷时频繁连接和断开，APNS有可能会封锁你的IP。</p>
<p>如Apple <a href="http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4">描述</a>:</p>
<blockquote><p>原生接口使用原生socket，具有二进制内容，采用数据流技术，不产生回馈。</p>
</blockquote>
<p><a href="http://boxedice.files.wordpress.com/2009/07/aps_provider_binary.jpg"><img title="APNS Binary Format" src="http://boxedice.files.wordpress.com/2009/07/aps_provider_binary.jpg?w=522&amp;h=111" alt="APNS Binary Format" width="522" height="111" /></a></p>
<h3><strong> </strong> </h3>
<h3><strong>打开连接</strong></h3>
<p><br class="spacer_" /></p>
<p>打开连接的 PHP 5代码如下：</p>
<pre>$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-dev.pem';

$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);

$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2,
STREAM_CLIENT_CONNECT, $streamContext);</pre>
<p><br class="spacer_" /></p>
<p>如果发送错误，你可以参考$errorString。它也包括了SSL许可证不正确时的详细信息。</p>
<p><br class="spacer_" /></p>
<p>许可证文件处于执行的PHP代码的当前工作目录下，如果需要你可指定其绝对路径。</p>
<p>注意测试时应该使用开发许可证及sandbox。成品主机名为 gateway.push.apple.com ，而且你必须使用不同的产品许可证。</p>
<h3><strong> </strong> </h3>
<h3><strong>发送载荷</strong></h3>
<p><br class="spacer_" /></p>
<p>在此，我们循环整个载荷队列进行发送。构建发送到APNS的二进制内容简单示例如下：</p>
<pre>$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) .
chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);</pre>
<p><br class="spacer_" /></p>
<p>注意 $deviceToken 是从数据库中提取并去除空格得到的。我们还应该检查是否$payload超过256个字节。</p>
<p><br class="spacer_" /></p>
<p>$apnsMessage 包括了正确的二进制载荷，而fwrite 将载荷写入当前活动的数据流连接中。</p>
<p><br class="spacer_" /></p>
<p>完成后，应关闭连接：</p>
<pre>socket_close($apns);
fclose($apns);</pre>
<p><strong> </strong> </p>
<p><strong>php-apns</strong></p>
<p><br class="spacer_" /></p>
<p>有一个开源服务器库<a href="http://code.google.com/p/php-apns/">php-apns</a>实现了以上所有功能，它依赖于 <a href="http://www.danga.com/memcached/">memcached</a>。我们不想使用任何第三方代码，所以完全自己编写了自己的服务器。我们使用自定义cron系统，几秒钟运行一次。</p>
<h5> </h5>
<h5>原文见：<a href="http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/">How to build an Apple Push Notification provider server (tutorial)</a></h5>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%80%8e%e6%a0%b7%e7%bc%96%e5%86%99apple-push-notification%e6%9c%8d%e5%8a%a1%e5%99%a8/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>一个可用在iPhone上的SMTP客户端程序</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%80%e4%b8%aa%e5%8f%af%e7%94%a8%e5%9c%a8iphone%e4%b8%8a%e7%9a%84smtp%e5%ae%a2%e6%88%b7%e7%ab%af%e7%a8%8b%e5%ba%8f</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%80%e4%b8%aa%e5%8f%af%e7%94%a8%e5%9c%a8iphone%e4%b8%8a%e7%9a%84smtp%e5%ae%a2%e6%88%b7%e7%ab%af%e7%a8%8b%e5%ba%8f#comments</comments>
		<pubDate>Sun, 29 Nov 2009 06:35:47 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[开源项目]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=364</guid>
		<description><![CDATA[虽然iPhone上可以直接调用email程序发送email，但如果你需要直接通过SMTP发送邮件，这个开源项目可能对你十分有帮助：
Quick SMTP client code for the iPhone
]]></description>
			<content:encoded><![CDATA[<p>虽然iPhone上可以直接调用email程序发送email，但如果你需要直接通过SMTP发送邮件，这个开源项目可能对你十分有帮助：</p>
<p><em><a id="project_summary_link" style="text-decoration: none; color: #000000;" href="http://code.google.com/p/skpsmtpmessage/">Quick SMTP client code for the iPhone</a></em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%80%e4%b8%aa%e5%8f%af%e7%94%a8%e5%9c%a8iphone%e4%b8%8a%e7%9a%84smtp%e5%ae%a2%e6%88%b7%e7%ab%af%e7%a8%8b%e5%ba%8f/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>通过NSURLRequest访问HTTP头信息</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e9%80%9a%e8%bf%87nsurlrequest%e8%ae%bf%e9%97%aehttp%e5%a4%b4%e4%bf%a1%e6%81%af</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e9%80%9a%e8%bf%87nsurlrequest%e8%ae%bf%e9%97%aehttp%e5%a4%b4%e4%bf%a1%e6%81%af#comments</comments>
		<pubDate>Wed, 08 Apr 2009 06:08:49 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[网络]]></category>

		<guid isPermaLink="false">http://iphonegeek.zuesitech.com/?p=152</guid>
		<description><![CDATA[
HTTP连接的头信息包括在NSHTPURLResponse类中。如果你拥有一个NSHTTPURLResponse变量，你可以通过发送allHeaderFields信息，轻而易举地获取以NSDictionary形式保存的头信息。

&#160;
对于一个同步请求 &#8211; 由于会引发阻塞所以不推荐使用 &#8211; 是很容易初始化一个NSHTTPURLResponse的：
&#160;
12345678910NSURL *url = &#91;NSURL URLWithString:@&#34;http://www.mobileorchard.com&#34;&#93;; 
NSURLRequest *request = &#91;NSURLRequest requestWithURL: url&#93;;
NSHTTPURLResponse *response;

&#91;NSURLConnection sendSynchronousRequest: request returningResponse: &#38;response error: nil&#93;; 
if &#40;&#91;response respondsToSelector:@selector&#40;allHeaderFields&#41;&#93;&#41;
&#123;
&#160; &#160; NSDictionary *dictionary = &#91;response allHeaderFields&#93;;
&#160; &#160; NSLog&#40;&#91;dictionary description&#93;&#41;;
&#125;
&#160;
而对于异步请求，你必须多做点工作。当回调connection:didReceiveResponse:被调用时，NSURLResponse会被作为第二个参数传递。你就可以象下面代码那样将其转化为NSHTTPURLResponse:  
&#160;
123456789- &#40;void&#41;connection:&#40;NSURLConnection *&#41;connection didReceiveResponse:&#40;NSURLResponse *&#41;response
&#123; &#160;
&#160; &#160; NSHTTPURLResponse *httpResponse = &#40;NSHTTPURLResponse*&#41;response;
&#160; &#160; if &#40;&#91;response respondsToSelector:@selector&#40;allHeaderFields&#41;&#93;&#41; 
&#160; &#160; &#123;
&#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>HTTP连接的头信息包括在NSHTPURLResponse类中。如果你拥有一个NSHTTPURLResponse变量，你可以通过发送allHeaderFields信息，轻而易举地获取以NSDictionary形式保存的头信息。</p>
<p><span id="more-152"></span></p>
<p>&nbsp;</p>
<p>对于一个同步请求 &#8211; 由于会引发阻塞所以不推荐使用 &#8211; 是很容易初始化一个NSHTTPURLResponse的：</p>
<p>&nbsp;</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>url <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> URLWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.mobileorchard.com&quot;</span><span style="color: #002200;">&#93;</span>; <br />
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/"><span style="color: #400080;">NSURLRequest</span></a> <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/"><span style="color: #400080;">NSURLRequest</span></a> requestWithURL<span style="color: #002200;">:</span> url<span style="color: #002200;">&#93;</span>;<br />
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/"><span style="color: #400080;">NSHTTPURLResponse</span></a> <span style="color: #002200;">*</span>response;<br />
<br />
<span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span style="color: #400080;">NSURLConnection</span></a> sendSynchronousRequest<span style="color: #002200;">:</span> request returningResponse<span style="color: #002200;">:</span> <span style="color: #002200;">&amp;</span>response error<span style="color: #002200;">:</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>; <br />
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>response respondsToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>allHeaderFields<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span>dictionary <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>response allHeaderFields<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>dictionary description<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>而对于异步请求，你必须多做点工作。当回调connection:didReceiveResponse:被调用时，NSURLResponse会被作为第二个参数传递。你就可以象下面代码那样将其转化为NSHTTPURLResponse:  </p>
<p>&nbsp;</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>connection<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span style="color: #400080;">NSURLConnection</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>connection didReceiveResponse<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLResponse_Class/"><span style="color: #400080;">NSURLResponse</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>response<br />
<span style="color: #002200;">&#123;</span> &nbsp;<br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/"><span style="color: #400080;">NSHTTPURLResponse</span></a> <span style="color: #002200;">*</span>httpResponse <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/"><span style="color: #400080;">NSHTTPURLResponse</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>response;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>response respondsToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>allHeaderFields<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span>dictionary <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>httpResponse allHeaderFields<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>dictionary description<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span> <br />
<span style="color: #002200;">&#125;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<div>
<h5>原文：<a href="http://www.mobileorchard.com/accessing-http-headers-from-an-nsurlrequest/">Accessing HTTP Headers From An NSURLRequest</a></h5>
<p>&nbsp;</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e9%80%9a%e8%bf%87nsurlrequest%e8%ae%bf%e9%97%aehttp%e5%a4%b4%e4%bf%a1%e6%81%af/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

