<?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/tag/%e6%8f%90%e7%a4%ba%e4%b8%8e%e6%8a%80%e5%b7%a7/feed" rel="self" type="application/rss+xml" />
	<link>http://www.iphone-geek.cn</link>
	<description>iPhone 新闻，编程，技巧与提示，代码，教程</description>
	<lastBuildDate>Sun, 25 Jul 2010 13:49:13 +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>不通过App Store发布程序</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%8d%e9%80%9a%e8%bf%87app-store%e5%8f%91%e5%b8%83%e7%a8%8b%e5%ba%8f</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%8d%e9%80%9a%e8%bf%87app-store%e5%8f%91%e5%b8%83%e7%a8%8b%e5%ba%8f#comments</comments>
		<pubDate>Sat, 17 Jul 2010 15:42:37 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[图形图像]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[程序发布]]></category>
		<category><![CDATA[系统安装]]></category>
		<category><![CDATA[提示与技巧]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=972</guid>
		<description><![CDATA[在一些情况下，我们需要不通过App Store发布程序，比如：


发布前的测试
企业内部自用软件，不需要发布到App Store


非正规的做法当然是“越狱”，但是更为正式的做法是使用Ad-Hoc。至于怎样创建Ad-Hoc provision文件，不在本文讨论的范围内。本文讨论的是怎样安装Ad-hoc发布的程序。通常的做法是:


开发者将Xcode编译的Ad-Hoc程序.app文件压缩后与.mobileprovision一起传给用户。
用户拖动.mobileprovision文件到iTunes下的资料库 → 应用程序中
将压缩的.app文件解压，然后将整个.app文件夹拖动到iTunes下的资料库 → 应用程序中


通常这对于Mac用户没有什么问题，但有时Windows用户会遇到一些问题。所以更好的做法是将.app制作成.ipa与.mobileprovision文件一同寄给用户。下面是制作ipa的步骤：

mkdir Payload
cp -rp MyApplication.app Payload/
zip -r MyApplication.ipa iTunesArtwork Payload


需要注意的是这里使用的是zip命令而不是Find中“Compress”选项，因为它会添加一些额外的内容。另外iTunesArtwork是一个512&#215;512的png文件（注意无后缀），它将在iTunes中增加一个图标，所以这并不是必需的。
]]></description>
			<content:encoded><![CDATA[<p>在一些情况下，我们需要不通过App Store发布程序，比如：</p>
<p><br class="spacer_" /></p>
<ol>
<li>发布前的测试</li>
<li>企业内部自用软件，不需要发布到App Store</li>
</ol>
<p><br class="spacer_" /></p>
<p>非正规的做法当然是“越狱”，但是更为正式的做法是使用Ad-Hoc。至于怎样创建Ad-Hoc provision文件，不在本文讨论的范围内。本文讨论的是怎样安装Ad-hoc发布的程序。通常的做法是:</p>
<p><br class="spacer_" /></p>
<ol>
<li>开发者将Xcode编译的Ad-Hoc程序.app文件压缩后与<tt>.mobileprovision</tt>一起传给用户。</li>
<li>用户拖动<tt>.mobileprovision文件到iTunes下的</tt><strong>资料库</strong> → <strong>应用程序</strong>中</li>
<li>将压缩的.app文件解压，然后将整个.app文件夹拖动到<tt>iTunes下的</tt><strong>资料库</strong> → <strong>应用程序</strong>中</li>
</ol>
<p><br class="spacer_" /></p>
<p>通常这对于Mac用户没有什么问题，但有时Windows用户会遇到一些问题。所以更好的做法是将.app制作成.ipa与.mobileprovision文件一同寄给用户。下面是制作ipa的步骤：</p>
<p><br class="spacer_" /></p>
<pre style="font-family: monospace; padding-left: 30px;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> Payload
<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-rp</span> MyApplication.app Payload<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #c20cb9; font-weight: bold;">zip</span> <span style="color: #660033;">-r</span> MyApplication.ipa iTunesArtwork Payload
</pre>
<p><br class="spacer_" /></p>
<p>需要注意的是这里使用的是zip命令而不是Find中“Compress”选项，因为它会添加一些额外的内容。另外iTunesArtwork是一个512&#215;512的png文件（注意无后缀），它将在iTunes中增加一个图标，所以这并不是必需的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%8d%e9%80%9a%e8%bf%87app-store%e5%8f%91%e5%b8%83%e7%a8%8b%e5%ba%8f/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>使用Javascript和PHP检测iPhone/iPod的使用</title>
		<link>http://www.iphone-geek.cn/%e7%bd%91%e9%a1%b5%e8%ae%be%e8%ae%a1/%e4%bd%bf%e7%94%a8javascript%e5%92%8cphp%e6%a3%80%e6%b5%8biphoneipod%e7%9a%84%e4%bd%bf%e7%94%a8</link>
		<comments>http://www.iphone-geek.cn/%e7%bd%91%e9%a1%b5%e8%ae%be%e8%ae%a1/%e4%bd%bf%e7%94%a8javascript%e5%92%8cphp%e6%a3%80%e6%b5%8biphoneipod%e7%9a%84%e4%bd%bf%e7%94%a8#comments</comments>
		<pubDate>Thu, 17 Jun 2010 02:53:02 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[网页设计]]></category>
		<category><![CDATA[网站开发]]></category>
		<category><![CDATA[提示与技巧]]></category>
		<category><![CDATA[代码片段]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=967</guid>
		<description><![CDATA[这与iPhone编程无关，不过当你的网站需要为iPhone/iPod进行优化时，可能会需要使用下面的技术：

使用Javascript检测是否正在使用iPhone 和 iPod

如果你的网页需要支持iPhone和iPod Touch，首先你必须检测到是否正在使用iPhone和iPod Touch，这样你才可能为其使用特定的代码或样页式。下列代码段使用Javascript来检测iPhone/iPod Touch的使用，从而将网页重定向iPhone相关的网页。

123456&#60;br /&#62;
if&#40;&#40;navigator.userAgent.match&#40;/iPhone/i&#41;&#41; &#124;&#124; &#40;navigator.userAgent.match&#40;/iPod/i&#41;&#41;&#41; &#123;&#60;br /&#62;
&#160; &#160; if &#40;document.cookie.indexOf&#40;&#34;iphone_redirect=false&#34;&#41; == -1&#41; &#123;&#60;br /&#62;
&#160; &#160; &#160; &#160; window.location = &#34;http://m.espn.go.com/wireless/?iphone&#38;i=COMR&#34;;&#60;br /&#62;
&#160; &#160; &#125;&#60;br /&#62;
&#125;&#60;br /&#62;

 
使用PHP检测是否正在使用 iPhone 和 iPod

有时在iPhone上，Javascript被禁止使用。为检测到iPhone/iPod Touch的使用，你需要使用下列PHP代码：

12345&#60;br /&#62;
if&#40;strstr&#40;$_SERVER&#91;'HTTP_USER_AGENT'&#93;,'iPhone'&#41; &#124;&#124; strstr&#40;$_SERVER&#91;'HTTP_USER_AGENT'&#93;,'iPod'&#41;&#41; &#123;&#60;br /&#62;
&#160; &#160; header&#40;'Location: http://yoursite.com/iphone'&#41;;&#60;br /&#62;
&#160; &#160; exit&#40;&#41;;&#60;br /&#62;
&#125;&#60;br /&#62;
]]></description>
			<content:encoded><![CDATA[<p>这与iPhone编程无关，不过当你的网站需要为iPhone/iPod进行优化时，可能会需要使用下面的技术：</p>
<p><br class="spacer_" /></p>
<h2>使用Javascript检测是否正在使用iPhone 和 iPod</h2>
<p><br class="spacer_" /></p>
<p>如果你的网页需要支持iPhone和iPod Touch，首先你必须检测到是否正在使用iPhone和iPod Touch，这样你才可能为其使用特定的代码或样页式。下列代码段使用Javascript来检测iPhone/iPod Touch的使用，从而将网页重定向iPhone相关的网页。</p>
<p><br class="spacer_" /></p>
<p><div class="codecolorer-container java 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 /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>navigator.<span style="color: #006633;">userAgent</span>.<span style="color: #006633;">match</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">/</span>iPhone<span style="color: #339933;">/</span>i<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>navigator.<span style="color: #006633;">userAgent</span>.<span style="color: #006633;">match</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">/</span>iPod<span style="color: #339933;">/</span>i<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>document.<span style="color: #006633;">cookie</span>.<span style="color: #006633;">indexOf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;iphone_redirect=false&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; window.<span style="color: #006633;">location</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;http://m.espn.go.com/wireless/?iphone&amp;i=COMR&quot;</span><span style="color: #339933;">;&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span></div></td></tr></tbody></table></div>
</p>
<h2> </h2>
<h2>使用PHP检测是否正在使用 iPhone 和 iPod</h2>
<p><br class="spacer_" /></p>
<p>有时在iPhone上，Javascript被禁止使用。为检测到iPhone/iPod Touch的使用，你需要使用下列PHP代码：</p>
<p><br class="spacer_" /></p>
<p><div class="codecolorer-container php 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 /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/strstr"><span style="color: #990000;">strstr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_USER_AGENT'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'iPhone'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <a href="http://www.php.net/strstr"><span style="color: #990000;">strstr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_USER_AGENT'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'iPod'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
&nbsp; &nbsp; <a href="http://www.php.net/header"><span style="color: #990000;">header</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: http://yoursite.com/iphone'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
&nbsp; &nbsp; <a href="http://www.php.net/exit"><span style="color: #990000;">exit</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;&lt;</span>br <span style="color: #339933;">/&gt;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span></div></td></tr></tbody></table></div></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bd%91%e9%a1%b5%e8%ae%be%e8%ae%a1/%e4%bd%bf%e7%94%a8javascript%e5%92%8cphp%e6%a3%80%e6%b5%8biphoneipod%e7%9a%84%e4%bd%bf%e7%94%a8/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iPhone不是Mac Pro</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e4%b8%8d%e6%98%afmac-pro</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e4%b8%8d%e6%98%afmac-pro#comments</comments>
		<pubDate>Tue, 09 Feb 2010 05:21:03 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[基础]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[提示与技巧]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=359</guid>
		<description><![CDATA[本文是关于通过Objective C++的强大功能提高iPhone程序的性能。通过讨论现实世界中Savoy的Spots应用程序遇到的问题，本文展示了通过3个步骤对程序进行优化使其顺利运行的过程。




使用Objective C++提高iPhone应用程序的性能

我十分喜爱软件开发的一个原因是总是会遇到这样那样的问题，而总能找到相应的解决方法。在开发Spots时，我多次遇到了UI设计的问题。为  iPhone设计一个精简的用户界面是不容易的。比如，我应该提供一个提供者过滤器（指Hotspot）按钮或将其放在Settings.app中？关于这个问题，我至少改变了二十次主意？

本文不是关于用户界面设计而是有关编程与性能。本文并不是针对用户界面而是有关编程和性能。一个最大的难题是地图的绘制（屏幕下方的长方形）。经过几种方法的试用，我发现在绘制230，000个点时，只有使用OpenGL以及大量的旁门左道才能使绘图的性能勉强被接受。根据放大的级别以及可见点点数量，我最后使用了三种不同的技术。由于我需要地图交互动作（拖动和缩放）尽可能地平滑，理想情况下为60HZ，性能是最为重要的问题。



本文中我将分享一些能提高性能的技术。虽然它们都很简单和直接，但因为在Cocoa中很少见，所以我还是花了不少时间。例如，尽管C++和Objective  C可以非常高效地混合使用，但我在Cocoa中并没有见到许多C++。当你的目标是高性能时，Objective  C++是纯Cocoa的很好的扩展。而在iPhone上，性能是应该首先需要考虑到因素。

难题

对于分布在一个矩形区域包括230，000个热点位置的地图（麦卡托投影的世界地图 the world map in mercator  projection），首先必须清楚当前地图矩形区域中有多少个可见点，因为此数值可以决定使用何种绘图技术。指标值必须归一，因此整个地图覆盖了一个{{0.0,  1.0}, {0.0, 1.0}}的矩形区域。通常情况下，程序使用的地图矩形是很小的：通常小于整个地图宽度和高度的百分之二。




但是我怎样有效地在数据库成千上万的点中找到可见点的数量？

我准备了一个XCode项目，它包括了这里讨论的所有代码。此示例项目并未包括了所有点的原始数据库。它仅包含了一些世界地图上的随机数据。虽然与真实情况有所区别，但它们的处理方法与我收集的原始数据的大同小异。

第一种方法: 普通Cocoa方法

第一种方法十分简单而且并没有采用十分高效的方法。使用Object C对象（@class  Spot）来表示位置，它们以NSArrary的形式被保存在一个数据库对象中（@class SpotsDB1）。
@interface Spot : NSObject {
    CGPoint _position;
}
@property (nonatomic) CGPoint position;
@end

@interface SpotsDB1 : NSObject {
    NSArray* _spots;
}
- (NSUInteger)countSpotsInRect:(CGRect)rect;
@end

为进行一个指定CGRect内地位置计数，数据库对象简单地循环整个数组并检查各位置。

NSUInteger count = 0;
 for (Spot* spot in _spots) {
 [...]]]></description>
			<content:encoded><![CDATA[<p>本文是关于通过Objective C++的强大功能提高iPhone程序的性能。通过讨论现实世界中Savoy的<a href="http://www.savoysoftware.com/spots/">Spots</a>应用程序遇到的问题，本文展示了通过3个步骤对程序进行优化使其顺利运行的过程。</p>
<p><br class="spacer_" /></p>
<p><a href="http://www.savoysoftware.com/spots/"><img title="spots-icon-big" src="http://savoysoftware.com/blog/wp-content/uploads/2008/12/spots-icon-big.png" alt="Spots" width="165" height="165" /></a></p>
<p><br class="spacer_" /></p>
<p><img title="More..." src="../wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /><span id="more-359"></span></p>
<h3><strong>使用Objective C++提高iPhone应用程序的性能</strong></h3>
<p><br class="spacer_" /></p>
<p>我十分喜爱软件开发的一个原因是总是会遇到这样那样的问题，而总能找到相应的解决方法。在开发Spots时，我多次遇到了UI设计的问题。为  iPhone设计一个精简的用户界面是不容易的。比如，我应该提供一个提供者过滤器（指Hotspot）按钮或将其放在Settings.app中？关于这个问题，我至少改变了二十次主意？</p>
<p><br class="spacer_" /></p>
<p>本文不是关于用户界面设计而是有关编程与性能。本文并不是针对用户界面而是有关编程和性能。一个最大的难题是地图的绘制（屏幕下方的长方形）。经过几种方法的试用，我发现在绘制230，000个点时，只有使用OpenGL以及大量的旁门左道才能使绘图的性能勉强被接受。根据放大的级别以及可见点点数量，我最后使用了三种不同的技术。由于我需要地图交互动作（拖动和缩放）尽可能地平滑，理想情况下为60HZ，性能是最为重要的问题。</p>
<p><br class="spacer_" /></p>
<p><img title="map_spots" src="http://savoysoftware.com/blog/wp-content/uploads/2009/01/map_spots.png" alt="map_spots" width="320" height="211" /></p>
<p><br class="spacer_" /></p>
<p>本文中我将分享一些能提高性能的技术。虽然它们都很简单和直接，但因为在Cocoa中很少见，所以我还是花了不少时间。例如，尽管C++和Objective  C可以非常高效地混合使用，但我在Cocoa中并没有见到许多C++。当你的目标是高性能时，Objective  C++是纯Cocoa的很好的扩展。而在iPhone上，性能是应该首先需要考虑到因素。</p>
<p><br class="spacer_" /></p>
<h4><strong>难题</strong></h4>
<p><br class="spacer_" /></p>
<p>对于分布在一个矩形区域包括230，000个热点位置的地图（麦卡托投影的世界地图 the world map in mercator  projection），首先必须清楚当前地图矩形区域中有多少个可见点，因为此数值可以决定使用何种绘图技术。指标值必须归一，因此整个地图覆盖了一个{{0.0,  1.0}, {0.0, 1.0}}的矩形区域。通常情况下，程序使用的地图矩形是很小的：通常小于整个地图宽度和高度的百分之二。</p>
<p><br class="spacer_" /></p>
<p><br class="spacer_" /></p>
<p><img title="map" src="http://savoysoftware.com/blog/wp-content/uploads/2009/01/map.png" alt="map" width="453" height="343" /></p>
<p><br class="spacer_" /></p>
<p>但是我怎样有效地在数据库成千上万的点中找到可见点的数量？</p>
<p><br class="spacer_" /></p>
<p>我准备了一个<a href="http://savoysoftware.com/blog/wp-content/uploads/2009/01/spotsdb.zip">XCode项目</a>，它包括了这里讨论的所有代码。此示例项目并未包括了所有点的原始数据库。它仅包含了一些世界地图上的随机数据。虽然与真实情况有所区别，但它们的处理方法与我收集的原始数据的大同小异。</p>
<p><br class="spacer_" /></p>
<h5>第一种方法: 普通Cocoa方法</h5>
<p><br class="spacer_" /></p>
<p>第一种方法十分简单而且并没有采用十分高效的方法。使用Object C对象（@class  Spot）来表示位置，它们以NSArrary的形式被保存在一个数据库对象中（@class SpotsDB1）。</p>
<pre>@interface Spot : NSObject {
    CGPoint _position;
}
@property (nonatomic) CGPoint position;
@end

@interface SpotsDB1 : NSObject {
    NSArray* _spots;
}
- (NSUInteger)countSpotsInRect:(CGRect)rect;
@end</pre>
<p><br class="spacer_" /></p>
<p>为进行一个指定CGRect内地位置计数，数据库对象简单地循环整个数组并检查各位置。</p>
<p><br class="spacer_" /></p>
<p>NSUInteger count = 0;<br />
 for (Spot* spot in _spots) {<br />
 if  (CGRectContainsPoint(aRect, spot.position))<br />
 ++count;<br />
 }</p>
<p><br class="spacer_" /></p>
<p>使用上述代码，在总数为230，000个点的区域上的任意一个{0.02,  0.02}矩形内进行计数大概需要250毫秒。太糟糕了，如果你的目标是刷新率60Hz，那么你只有16  ms绘制一帧。使得此方案过慢的原因不仅在于其缺乏聪明的算法，而且在循环中浪费了许多时间在调用了几个函数上。另一个对性能产生负面影响的因素是位置被保存在NSArray中的对象，这是由于对象占用了大量的内存以及数组指针的非直接性导致了处理器时间的增加。</p>
<p><br class="spacer_" /></p>
<h5>第二种方法: 简单优化</h5>
<p><br class="spacer_" /></p>
<p>为使同样的方案运行得更快，我们只需简单地将位置存储与一个更为紧凑的数据结构中：一个CGPoint结构的标准C数组。为使用方便，我们将C数组保存在一个NSMutableData  对象中。</p>
<p><br class="spacer_" /></p>
<p>_spotCount = [spots count];<br />
 _spotsData = [[NSMutableData alloc]  init];<br />
 for (Spot* spot in spots) {<br />
 CGPoint p = spot.position;<br />
 [data appendBytes:&amp;p length:sizeof(CGPoint)];<br />
 }</p>
<p><br class="spacer_" /></p>
<p>消除了循环内函数调用的负面影响，我们使得性能有四倍的提升：</p>
<p><br class="spacer_" /></p>
<p>CGFloat xMin = CGRectGetMinX(aRect);<br />
 CGFloat yMin =  CGRectGetMinY(aRect);<br />
 CGFloat xMax = CGRectGetMaxX(aRect);<br />
 CGFloat yMax =  CGRectGetMaxY(aRect);</p>
<p>CGPoint* begin = (CGPoint*)[_spotsData  bytes];<br />
 CGPoint* end = begin + _spotCount;</p>
<p>NSUInteger count =  0;<br />
 for (CGPoint* i = begin; i != end; ++i) {<br />
 if (i-&gt;x &gt; xMin  &amp;&amp; i-&gt;y &gt; yMin &amp;&amp; i-&gt;x &lt; xMax &amp;&amp; i-&gt;y  &lt; yMax)<br />
 ++count;<br />
 }</p>
<p><br class="spacer_" /></p>
<p>在没有改变基本算法的基础上，点计数的计算现在只需55毫秒，这大概比原来方法快了四倍。另一个好处是现在使用的内存是原来版本的一半。</p>
<h5>第三种方法：算法优化</h5>
<p><br class="spacer_" /></p>
<p>当然，还有许多聪明的方法来优化平面地图点的查询。例如，你可以使用四边形树来保存这些点。在本例中我使用了一种比较简单的解决方案，所以没有涉及数据存储的方式。我使用了C++的内置功能所以甚至不需要写任何代码来处理数据的存储。</p>
<p><br class="spacer_" /></p>
<p><img title="sorted" src="http://savoysoftware.com/blog/wp-content/uploads/2009/01/sorted.png" alt="sorted" width="355" height="343" /></p>
<p><br class="spacer_" /></p>
<p>我的设想是将数组中的位置从左至右分类。这样做的好处是确定指定正方形的左右边界十分快速（见下图）。当数组中边界已知时，仅需要检查边界间的点。</p>
<p><br class="spacer_" /></p>
<p><img title="sorted2" src="http://savoysoftware.com/blog/wp-content/uploads/2009/01/sorted2.png" alt="sorted2" width="355" height="343" /></p>
<p><br class="spacer_" /></p>
<p>所以此算法是有关快速寻找边界的。我们使用的是<a href="http://en.wikipedia.org/wiki/Binary_search">二进制搜索</a>，  它适用于已排序的数组。它并不检查每个值以找到匹配的位置，而是直接跳到数组的中点，检查其值是小于还是大于给点值，然后跳到剩余部分的中心点，重复以上步骤。使用这种方法，二进制搜索需要  log2(n)的时间来查找最佳元素。对于一个拥有230，000个位置的数组，只需22次搜索！回到代码，我们发现上述算法的实现是很简单的。当然，我们必须为数据库排序：</p>
<pre>// comparison function for array sorting
NSInteger leftToRight(Spot* a, Spot* b, void* context) {
    CGFloat xa = a.position.x;
    CGFloat xb = b.position.x;
    if (xa &lt; xb)
        return NSOrderedAscending;
    return xa &gt; xb ? NSOrderedDescending : NSOrderedSame;
}

...

spots = [spots sortedArrayUsingFunction:leftToRight context:NULL];</pre>
<p><br class="spacer_" /></p>
<p>现在是有趣的部分：使用C++进行二进制搜索。我们使用了#include &lt;algorithm&gt;中的库函数  std::lower_bound。它需要一个起点，终点，要查找的值以及比较函数。它返回比较为false的第一个值。起点和终点可以是简单的<span style="font-family: 微软雅黑;">指向数组的C指针。</span></p>
<p><br class="spacer_" /></p>
<p>#include &lt;algorithm&gt;<br />
 &#8230;</p>
<p>bool cmpX(const  CGPoint&amp; a, const CGPoint&amp; b) {<br />
 return a.x &lt;  b.x;<br />
 }<br />
 &#8230;</p>
<p>CGFloat yMin = CGRectGetMinY(aRect);<br />
 CGFloat yMax =  CGRectGetMaxY(aRect);</p>
<p>CGPoint* begin = (CGPoint*)[_spotsData  bytes];<br />
 CGPoint* end = begin + _spotCount;</p>
<p>CGPoint leftMargin =  aRect.origin;<br />
 CGPoint rightMargin;<br />
 rightMargin.x =  CGRectGetMaxX(aRect);</p>
<p>CGPoint* left  = std::lower_bound(begin, end,  leftMargin, cmpX);<br />
 CGPoint* right = std::lower_bound(left, end, rightMargin,  cmpX);</p>
<p>NSUInteger count = 0;<br />
 for (CGPoint* i = left; i != right; ++i)  {<br />
 if (i-&gt;y &gt; yMin &amp;&amp; i-&gt;y &lt; yMax)<br />
 ++count;<br />
 }</p>
<p><br class="spacer_" /></p>
<p>注意第二个二进制搜索，它仅从左边界而不是整个数组查找右边界。另一个优化是从循环中移除X-轴的检查，这是因为已经通过指定边界完成了这部分工作。</p>
<p><br class="spacer_" /></p>
<p>通过这些优化，只需要1毫秒来对长方形进行计数。这是第一个版本的200倍。</p>
<h5>结果</h5>
<p><br class="spacer_" /></p>
<p>下面是运行在三种不同设备上的<a href="http://savoysoftware.com/blog/wp-content/uploads/2009/01/spotsdb.zip">示例项目</a>的输出。如果你需要运行在你自己的设备上，你只需将目标设定中将代码签名标识符改为自己的。如果你不希望用在通用标识符的程序上，你还需要更改Info.plist中的包标识符（Bundle  Identifier）。</p>
<p><br class="spacer_" /></p>
<p>iPhone 3G：</p>
<pre>SpotsDB1 needed 3.2 seconds to count spots in 13 rects
that's 244.423 ms per rect
SpotsDB2 needed 3.0 seconds to count spots in 55 rects
that's 55.230 ms per rect
SpotsDB3 needed 3.0 seconds to count spots in 2988 rects
that's 1.004 ms per rect</pre>
<p>第二代iPod Touch：</p>
<pre>SpotsDB1 needed 3.1 seconds to count spots in 16 rects
that's 194.756 ms per rect
SpotsDB2 needed 3.0 seconds to count spots in 65 rects
that's 46.450 ms per rect
SpotsDB3 needed 3.0 seconds to count spots in 3399 rects
that's 0.883 ms per rect</pre>
<p>运行在Mac Pro之上的模拟器：</p>
<pre>SpotsDB1 needed 3.0 seconds to count spots in 687 rects
that's 4.372 ms per rect
SpotsDB2 needed 3.0 seconds to count spots in 2687 rects
that's 1.117 ms per rect
SpotsDB3 needed 3.0 seconds to count spots in 187276 rects
that's 0.016 ms per rect</pre>
<h5>结论</h5>
<p><br class="spacer_" /></p>
<p>观察结果我们可以看出在桌面电脑和iPhone上性能有显著的区别。有一个金科玉律是：在Mac上只需一秒的操作在iPhone上要一分钟。或者有一个更悲观的说法：Mac上60Hz的刷新率在iPhone上每秒钟只能更新一次。</p>
<p><br class="spacer_" /></p>
<p>所以显而易见在iPhone上进行优化是完全必须的。本文中我展示了几种方法来减小Object  C的开销以及怎样使用C++来获得最大的性能。当然找到性能的瓶颈并转而使用数据结构使代码性能提升并不总是很容易的事情。但是在设计一个使用大量数据的程序时，绝对有必要考虑使用非Cocoa的方法。</p>
<h6>原文见：<a href="http://www.savoysoftware.com/blog/?p=114">My iPhone is not a  Mac Pro</a></h6>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e4%b8%8d%e6%98%afmac-pro/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenAL系列之二 &#8211; 为什么要避免使用alBuferDataStatic</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/openal%e7%b3%bb%e5%88%97%e4%b9%8b%e4%ba%8c-%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e9%81%bf%e5%85%8d%e4%bd%bf%e7%94%a8albuferdatastatic</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/openal%e7%b3%bb%e5%88%97%e4%b9%8b%e4%ba%8c-%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e9%81%bf%e5%85%8d%e4%bd%bf%e7%94%a8albuferdatastatic#comments</comments>
		<pubDate>Thu, 31 Dec 2009 11:08:04 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[音频]]></category>
		<category><![CDATA[OpenAL]]></category>
		<category><![CDATA[提示与技巧]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=704</guid>
		<description><![CDATA[我收到Ken一封Email，这位仁兄浏览了我博客的中有关OpenAL的文章，遇到一些问题请求我的帮助。他在加载缓存后重复使用时遇到了一些OpenAL神秘的错误。
&#160;
所以我阅读了他寄给我的代码片段，我注意到：
&#160;
123// use the static buffer data API

alBufferDataStaticProc&#40;buffer, format, data, size, freq&#41;;
&#160;
啊哈! 这可能就是你问题的根源！除非你真正需要，alBufferDataStatic应该完全被避免。你怎样才知道你需要使用它？有一条金桂玉律：如果你不知道这个问题的答案，那么你就不需要它。
&#160;

（我不希望看上去对Ken太过严苛，这个问题很普遍，所以我决定写这篇文章（类似于我呼吁绝不要使用随Apple发布的示例代码一样））
&#160;
那我为什么会认为要避免使用它？我相信你一定听说过要获得更好的性能，你应该使用alBufferDataStatic()，对吗？不！
&#160;
那好，alBufferDataStatic()是什么？alBufferDataStatic将所有缓存数据的内存管理责任完全推给了你的代码。
&#160;
我重复一遍：当使用alBufferDataStatic()时，你应该对所有内存管理负责。
&#160;
这就是所谓的性能提升。
&#160;
等等！真的吗？这就是alBufferDataStatic的所作所为吗？
&#160;
是的。
&#160;
iPhone是共享内存空间的，它处理内存的方式以及当你的程序使用过多的内存时而被抛弃的方式是十分特殊的。它要求你密切注意及处理你使用的内存。那意味着如果你希望使你的第一人称射击游戏可以稳定地保持在30FPS，你必须从iPhone榨取最后一个字节内存，因此你可能需要花费几个星期来调整你的声音代码使得你可以随时密切控制内存使用情况。
&#160;
对于其他 %99.9999可能需要使用OpenAL的程序（即使你使用了大量的音效），使用alBufferDataStatic()只不过是给你带来额外的麻烦而已。这里有另一条规则：如果你不打算专门雇佣一个全职开发者处理音效代码，那么你不需要使用alBufferDataStatic()。
&#160;
快速阅读一下有关alBufferDataStatic()的技术文档。
&#160;
这是什么意思？
&#160;
意思是: 当你使用alBufferData()时，你将加载声音数据到局部缓存（你使用malloc建立的缓存），当你调用alBufferData()时， OpenAL 将复制所有字节到它自己的缓存区。然后，你要释放局部缓存，OpenGL现在拥有自己的缓存。其缺点是：在很短的一段时间内，你将拥有两份声音数据在内存中。优点是：内存管理非常非常容易。
&#160;
如果你的程序在缓存复制时崩溃，那么你可能需要alBufferDataStatic()。但是更有可能的是你的内存管理机制在什么地方十分糟糕。（另外需要注意如果你加载一个很大的声音数据到内存中，那么我可以告诉你，这是错误的，你应该采用数据流来加载数据）。
&#160;
好了，你已经绝对地肯定你要管理你自己的声音内存？可能需要使用alBufferDataStatic()，但是首先：这里有另一条金桂玉律：如果你正在读我这篇文章来决定是否使用它；那么不要使用。赶快找到这条代码，赶快删除它。直接删除。
&#160;
很明显，我在用一种夸张的方式试图说明我的观点。我不知道你的代码，但这里有一些我在我的代码中经常出现的bug：
&#160;
忘记释放对象导致内存泄漏，最终导致程序崩溃。
&#160;
不小心释放了一个自动释放对象，引起崩溃。
&#160;
不小心释放了一个从属于其他对象的对象，使程序随后（很久很久以后）崩溃。
&#160;
malloc了一些内存，忘记free，引起泄漏，最终崩溃。
&#160;
free了一些 malloc的内存，然后试图再使用，引起程序完全疯狂。
&#160;
这个列表还可以继续。但是你看到一个共同点没有？内存。为什么我在不必要的情况下还要承担更多内存管理的责任？为什么开发者还要一如既往地使他们的生活变得更糟糕？
&#160;
这里有些陈词滥调：
&#160;
更少的代码 == 更少的bug  更多的代码== 更多的bug。 因此代码越少越好。
&#160;
不要添加你现在不需要的代码。（这很常见，你可能会想：我可能以后做X时会需要一个方法，所以我现在就写出来，不必等到用时在写。）错！“未来”当你需要时，你需要的是Y，而不是X，你还是需要重写。或者更有可能是你永远也不需要用到X，你只是浪费了时间在不必要的代码上。
&#160;
不要过早地进行优化。使代码可以工作为先。然后再找到你需要优化的地方。如果试图过早优化，那么最终的结果是你花费了所有的时间在使一个方法十分伟大（直到后来才知道此方法仅仅几秒钟才被调用一次，所以这是一段最缺乏效率的代码而且没有人会注意到它。）
&#160;
所以，使用alBufferDataStatic()将打破我可爱的全部三条陈词滥调。
&#160;
不要这样做。
&#160;
你只会让你自己图添悲伤而且你的代码会问题多多。请使用alBufferData()。它可以工作。它很容易。资深的使用OpenAL的工程师保证使用alBufferData()没有内存问题。如果你打算移植你的代码，alBufferData()还是可以工作！alBufferData() 使你呼吸更新鲜！
&#160;
我已经在6个程序中使用了OpenAL代码。一些是游戏，一些是实用程序。一个没有使用alBufferDataStatic()的“音板”式程序同时播放32个声音（这是目前允许的最大数目，可能以后仍然是），它能够处理庞大的声音文件（通过数据流）。是不是这个超级疯狂代码实现的超难任务可以算是一种技能？
&#160;
不。恰恰相反。我尽量使我的程序保存简单。
&#160;
保持代码简单，不要使用不需要的东西。
&#160;
原文见：alBufferDataStatic: why you should avoid it
]]></description>
			<content:encoded><![CDATA[<p>我收到Ken一封Email，这位仁兄浏览了我博客的中有关OpenAL的文章，遇到一些问题请求我的帮助。他在加载缓存后重复使用时遇到了一些OpenAL神秘的错误。</p>
<p>&nbsp;</p>
<p>所以我阅读了他寄给我的代码片段，我注意到：</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 /></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: #11740a; font-style: italic;">// use the static buffer data API</span><br />
<br />
alBufferDataStaticProc<span style="color: #002200;">&#40;</span>buffer, format, data, size, freq<span style="color: #002200;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>啊哈! 这可能就是你问题的根源！除非你真正需要，alBufferDataStatic应该完全被避免。你怎样才知道你需要使用它？有一条金桂玉律：如果你不知道这个问题的答案，那么你就不需要它。</p>
<p>&nbsp;</p>
<p><span id="more-704"></span><br />
（我不希望看上去对Ken太过严苛，这个问题很普遍，所以我决定写这篇文章（类似于我呼吁绝不要使用随Apple发布的示例代码一样））</p>
<p>&nbsp;</p>
<p>那我为什么会认为要避免使用它？我相信你一定听说过要获得更好的性能，你应该使用alBufferDataStatic()，对吗？不！</p>
<p>&nbsp;</p>
<p>那好，alBufferDataStatic()是什么？alBufferDataStatic将所有缓存数据的内存管理责任完全推给了你的代码。</p>
<p>&nbsp;</p>
<p>我重复一遍：当使用alBufferDataStatic()时，<strong>你</strong>应该对所有内存管理负责。</p>
<p>&nbsp;</p>
<p>这就是所谓的性能提升。</p>
<p>&nbsp;</p>
<p>等等！真的吗？这就是alBufferDataStatic的所作所为吗？</p>
<p>&nbsp;</p>
<p>是的。</p>
<p>&nbsp;</p>
<p>iPhone是共享内存空间的，它处理内存的方式以及当你的程序使用过多的内存时而被抛弃的方式是十分特殊的。它要求你密切注意及处理你使用的内存。那意味着如果你希望使你的第一人称射击游戏可以稳定地保持在30FPS，你必须从iPhone榨取最后一个字节内存，因此你可能需要花费几个星期来调整你的声音代码使得你可以随时密切控制内存使用情况。</p>
<p>&nbsp;</p>
<p>对于其他 %99.9999可能需要使用OpenAL的程序（即使你使用了大量的音效），使用alBufferDataStatic()只不过是给你带来额外的麻烦而已。这里有另一条规则：如果你不打算专门雇佣一个全职开发者处理音效代码，那么你不需要使用alBufferDataStatic()。</p>
<p>&nbsp;</p>
<p>快速阅读一下有关alBufferDataStatic()的技术文档。</p>
<p>&nbsp;</p>
<p>这是什么意思？</p>
<p>&nbsp;</p>
<p>意思是: 当你使用alBufferData()时，你将加载声音数据到局部缓存（你使用malloc建立的缓存），当你调用alBufferData()时， OpenAL 将复制所有字节到它自己的缓存区。然后，你要释放局部缓存，OpenGL现在拥有自己的缓存。其缺点是：在很短的一段时间内，你将拥有两份声音数据在内存中。优点是：内存管理非常非常容易。</p>
<p>&nbsp;</p>
<p>如果你的程序在缓存复制时崩溃，那么你可能需要alBufferDataStatic()。但是更有可能的是你的内存管理机制在什么地方十分糟糕。（另外需要注意如果你加载一个很大的声音数据到内存中，那么我可以告诉你，这是错误的，你应该采用数据流来加载数据）。</p>
<p>&nbsp;</p>
<p>好了，你已经绝对地肯定你要管理你自己的声音内存？可能需要使用alBufferDataStatic()，但是首先：这里有另一条金桂玉律：如果你正在读我这篇文章来决定是否使用它；那么不要使用。赶快找到这条代码，赶快删除它。直接删除。</p>
<p>&nbsp;</p>
<p>很明显，我在用一种夸张的方式试图说明我的观点。我不知道你的代码，但这里有一些我在我的代码中经常出现的bug：</p>
<p>&nbsp;</p>
<p>忘记释放对象导致内存泄漏，最终导致程序崩溃。</p>
<p>&nbsp;</p>
<p>不小心释放了一个自动释放对象，引起崩溃。</p>
<p>&nbsp;</p>
<p>不小心释放了一个从属于其他对象的对象，使程序随后（很久很久以后）崩溃。</p>
<p>&nbsp;</p>
<p>malloc了一些内存，忘记free，引起泄漏，最终崩溃。</p>
<p>&nbsp;</p>
<p>free了一些 malloc的内存，然后试图再使用，引起程序完全疯狂。</p>
<p>&nbsp;</p>
<p>这个列表还可以继续。但是你看到一个共同点没有？内存。为什么我在不必要的情况下还要承担更多内存管理的责任？为什么开发者还要一如既往地使他们的生活变得更糟糕？</p>
<p>&nbsp;</p>
<p>这里有些陈词滥调：</p>
<p>&nbsp;</p>
<p>更少的代码 == 更少的bug  更多的代码== 更多的bug。 因此代码越少越好。</p>
<p>&nbsp;</p>
<p>不要添加你现在不需要的代码。（这很常见，你可能会想：我可能以后做X时会需要一个方法，所以我现在就写出来，不必等到用时在写。）错！“未来”当你需要时，你需要的是Y，而不是X，你还是需要重写。或者更有可能是你永远也不需要用到X，你只是浪费了时间在不必要的代码上。</p>
<p>&nbsp;</p>
<p>不要过早地进行优化。使代码可以工作为先。然后再找到你需要优化的地方。如果试图过早优化，那么最终的结果是你花费了所有的时间在使一个方法十分伟大（直到后来才知道此方法仅仅几秒钟才被调用一次，所以这是一段最缺乏效率的代码而且没有人会注意到它。）</p>
<p>&nbsp;</p>
<p>所以，使用alBufferDataStatic()将打破我可爱的全部三条陈词滥调。</p>
<p>&nbsp;</p>
<p>不要这样做。</p>
<p>&nbsp;</p>
<p>你只会让你自己图添悲伤而且你的代码会问题多多。请使用alBufferData()。它可以工作。它很容易。资深的使用OpenAL的工程师保证使用alBufferData()没有内存问题。如果你打算移植你的代码，alBufferData()还是可以工作！alBufferData() 使你呼吸更新鲜！</p>
<p>&nbsp;</p>
<p>我已经在6个程序中使用了OpenAL代码。一些是游戏，一些是实用程序。一个没有使用alBufferDataStatic()的“音板”式程序同时播放32个声音（这是目前允许的最大数目，可能以后仍然是），它能够处理庞大的声音文件（通过数据流）。是不是这个超级疯狂代码实现的超难任务可以算是一种技能？</p>
<p>&nbsp;</p>
<p>不。恰恰相反。我尽量使我的程序保存简单。</p>
<p>&nbsp;</p>
<p>保持代码简单，不要使用不需要的东西。</p>
<p>&nbsp;</p>
<p>原文见：<a href="http://benbritten.com/2009/09/20/albufferdatastatic-why-you-should-avoid-it/">alBufferDataStatic: why you should avoid it</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/openal%e7%b3%bb%e5%88%97%e4%b9%8b%e4%ba%8c-%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e9%81%bf%e5%85%8d%e4%bd%bf%e7%94%a8albuferdatastatic/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>开始学习iPhone编程之四 &#8211; 所有iPhone apps都需要做的七件事</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%89%80%e6%9c%89iphone-apps%e9%83%bd%e9%9c%80%e8%a6%81%e5%81%9a%e7%9a%84%e4%b8%83%e4%bb%b6%e4%ba%8b</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%89%80%e6%9c%89iphone-apps%e9%83%bd%e9%9c%80%e8%a6%81%e5%81%9a%e7%9a%84%e4%b8%83%e4%bb%b6%e4%ba%8b#comments</comments>
		<pubDate>Wed, 09 Dec 2009 03:34:10 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[提示与技巧]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=352</guid>
		<description><![CDATA[想要开发iPod或iPhone程序？这里有一个列表，列出了要获得成功需要做到的七件事。
&#160;
如果你有一台iPhone或者iPod，那么你可能下载过一些程序。如果你下载了不止一个程序，那么你很快就会发现一些程序比另一些更好。
&#160;
开发者在编写程序时有许多选择；程序不但需要有一个很好的设想，而且需要以一种iPhone用户熟悉的方式展现出来。如果用户需要花上超过一分钟的时间来摸索这样使用你的程序，那么导致的结果可能是他们再也不会使用你的程序并且会给出一个低分。
&#160;
这两种结果都是不好的结果，特别是你希望在App Store中获得成功时，你的程序需要处于某个“Top”列表中。
&#160;
考虑到这些，我根据我的经验汇总了一个列表，将帮助你使你的iPhone程序获得成功。
&#160;

你的iPhone程序应该把一件事做好
&#160;
从最基本的地方设计你的程序，使其很好地完成一个功能。降低程序的复杂性减少掌握它的时间，用户越快熟悉你的程序，程序将显得越有用处。有很多好的例子说明了这点，比如：Things, Byline, Traffic Australia 以及Notes。

很好地完成一件任务并不意味着你不应该通过Preferences（偏好）提供配置选项，但是缺省的设置应该适用于90%的用户。
&#160;

确保程序很好地实现所有的功能

&#160;
如果你设计的程序需要实现很多功能，那么一定要很好地完成这些功能。一个好的例子是1Password。这是一个复杂的程序，它存储密码，笔记，参数随机密码以及提供与桌面客户端同步的能力。但是，如果你熟悉桌面客户端程序的话，你将会自动熟悉iPhone程序，所有的功能都如预料般工作。

&#160;

使用熟悉的图标和图像

&#160;
iPhone界面很棒正是由于其形象化。图标具有一定意义 &#8211; 看看随iPhone出厂程序的默认图标你就知道为什么。当你设计应用程序时也要遵循同样的准则。使用熟悉的图标，比如加号代表添加新的东西，星号代表收藏夹等等。仅在没有用户熟悉的图标存在时才考虑设计新图标。使用熟悉的图标可以使用户更好地理解你的程序。
&#160;

程序应该实现自动存储

&#160;
我简直无法相信许多程序不能记住退出时的状态。这对我而言，这简直就是失败，特别是对于像iPhone这类的设备，因为电话或SMS会中断你正在进行的工作。
&#160;
除此之外，iPhone并非十分稳定 &#8211; 你需要做好准备你的程序有可能崩溃。
&#160;

我要听音乐

&#160;
iPhone的一个主要功能是iPod程序。它是Apple允许的为数不多的几个可以运行在后台的特殊程序之一。请允许用户在运行你的程序的同时可以继续听音乐。游戏通常在这方面做得不好。如果你是一个游戏开发者，你应考虑允许用户在运行你的游戏时还可以继续听音乐，或至少提供一个选项让用户选择。
&#160;

如果可能，所有程序应该是位置感知的

&#160;
没有任何借口，我们的程序不能位置感知。如果程序能自动提供此信息，无疑会为用户提供更好的体验。
&#160;
另一方面，用户至少应能够手工输入位置信息。比如，AroundMe，我经常使用的程序，并未提供此功能。

&#160;

尽量减少启动时间


&#160;
这应该是毫无疑问的，并非针对iPhone，在其他手机平台上也应如此。一个程序启动越快，用户也会越觉得它有用。任何程序（游戏除外）如果启动时间超过5-8秒，就是太慢了。你可以在程序加载时通过启动画面造成程序已经加载的假象或显示程序“loading”（正在加载）。
&#160;
原文见：Seven things all iPhone apps need 作者：Danny Gorog
]]></description>
			<content:encoded><![CDATA[<p>想要开发iPod或iPhone程序？这里有一个列表，列出了要获得成功需要做到的七件事。</p>
<p>&nbsp;</p>
<div>如果你有一台iPhone或者iPod，那么你可能下载过一些程序。如果你下载了不止一个程序，那么你很快就会发现一些程序比另一些更好。</div>
<p>&nbsp;</p>
<div>开发者在编写程序时有许多选择；程序不但需要有一个很好的设想，而且需要以一种iPhone用户熟悉的方式展现出来。如果用户需要花上超过一分钟的时间来摸索这样使用你的程序，那么导致的结果可能是他们再也不会使用你的程序并且会给出一个低分。</div>
<p>&nbsp;</p>
<div>这两种结果都是不好的结果，特别是你希望在App Store中获得成功时，你的程序需要处于某个“Top”列表中。</div>
<p>&nbsp;</p>
<div>考虑到这些，我根据我的经验汇总了一个列表，将帮助你使你的iPhone程序获得成功。</div>
<p>&nbsp;</p>
<p><span id="more-352"></span></p>
<h2><span style="font-weight: bold;">你的iPhone程序应该把一件事做好</span></h2>
<p>&nbsp;</p>
<div>从最基本的地方设计你的程序，使其很好地完成一个功能。降低程序的复杂性减少掌握它的时间，用户越快熟悉你的程序，程序将显得越有用处。有很多好的例子说明了这点，比如：<span><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284971781&amp;mt=8">Things</a></span>, <span><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284946773&amp;mt=8">Byline</a></span>, <span><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=299282352&amp;mt=8">Traffic Australia</a></span> 以及Notes。</div>
<div><span><img src="http://apcmag.com/images/trafficaustralia.png" alt="" /></span></div>
<div>很好地完成一件任务并不意味着你不应该通过Preferences（偏好）提供配置选项，但是缺省的设置应该适用于90%的用户。</div>
<p>&nbsp;</p>
<div>
<h2><span style="font-weight: bold;">确保程序很好地实现所有的功能</span></h2>
</div>
<p>&nbsp;</p>
<div>如果你设计的程序需要实现很多功能，那么一定要很好地完成这些功能。一个好的例子是<span><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=285897618&amp;mt=8">1Password</a></span>。这是一个复杂的程序，它存储密码，笔记，参数随机密码以及提供与桌面客户端同步的能力。但是，如果你熟悉桌面客户端程序的话，你将会自动熟悉iPhone程序，所有的功能都如预料般工作。</div>
<div><span><img src="http://apcmag.com/images/1password.png" alt="" /></span></div>
<p>&nbsp;</p>
<div>
<h2><span style="font-weight: bold;">使用熟悉的图标和图像</span></h2>
</div>
<p>&nbsp;</p>
<div>iPhone界面很棒正是由于其形象化。图标具有一定意义 &#8211; 看看随iPhone出厂程序的默认图标你就知道为什么。当你设计应用程序时也要遵循同样的准则。使用熟悉的图标，比如加号代表添加新的东西，星号代表收藏夹等等。仅在没有用户熟悉的图标存在时才考虑设计新图标。使用熟悉的图标可以使用户更好地理解你的程序。</div>
<p>&nbsp;</p>
<div>
<h2><span style="font-weight: bold;">程序应该实现自动存储</span></h2>
</div>
<p>&nbsp;</p>
<div>我简直无法相信许多程序不能记住退出时的状态。这对我而言，这简直就是失败，特别是对于像iPhone这类的设备，因为电话或SMS会中断你正在进行的工作。</p>
<p>&nbsp;</p>
<p>除此之外，iPhone并非十分稳定 &#8211; 你需要做好准备你的程序有可能崩溃。</p></div>
<p>&nbsp;</p>
<div>
<h2><span style="font-weight: bold;">我要听音乐</span></h2>
</div>
<p>&nbsp;</p>
<div>iPhone的一个主要功能是iPod程序。它是Apple允许的为数不多的几个可以运行在后台的特殊程序之一。请允许用户在运行你的程序的同时可以继续听音乐。游戏通常在这方面做得不好。如果你是一个游戏开发者，你应考虑允许用户在运行你的游戏时还可以继续听音乐，或至少提供一个选项让用户选择。</div>
<p>&nbsp;</p>
<div>
<h2><span style="font-weight: bold;">如果可能，所有程序应该是位置感知的</span></h2>
</div>
<p>&nbsp;</p>
<div>没有任何借口，我们的程序不能位置感知。如果程序能自动提供此信息，无疑会为用户提供更好的体验。</p>
<p>&nbsp;</p>
<p>另一方面，用户至少应能够手工输入位置信息。比如，<span><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=290051590&amp;mt=8">AroundMe</a></span>，我经常使用的程序，并未提供此功能。</div>
<div><span><img src="http://apcmag.com/images/aroundme.png" alt="" /></span></div>
<p>&nbsp;</p>
<div>
<h2><span style="font-weight: bold;">尽量减少启动时间<br />
</span></h2>
</div>
<p>&nbsp;</p>
<div>这应该是毫无疑问的，并非针对iPhone，在其他手机平台上也应如此。一个程序启动越快，用户也会越觉得它有用。任何程序（游戏除外）如果启动时间超过5-8秒，就是太慢了。你可以在程序加载时通过启动画面造成程序已经加载的假象或显示程序“loading”（正在加载）。</div>
<p>&nbsp;</p>
<h5>原文见：<a href="http://apcmag.com/seven_things_all_iphone_apps_need.htm">Seven things all iPhone apps need</a> 作者：<strong><a href="http://apcmag.com/authors.htm?Aid=74">Danny Gorog</a></strong></h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%89%80%e6%9c%89iphone-apps%e9%83%bd%e9%9c%80%e8%a6%81%e5%81%9a%e7%9a%84%e4%b8%83%e4%bb%b6%e4%ba%8b/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>怎样替换Xcode中__MyCompanyName__</title>
		<link>http://www.iphone-geek.cn/%e6%8a%80%e5%b7%a7%e4%b8%8e%e6%8f%90%e7%a4%ba/%e6%80%8e%e6%a0%b7%e6%9b%bf%e6%8d%a2xcode%e4%b8%ad__mycompanyname__</link>
		<comments>http://www.iphone-geek.cn/%e6%8a%80%e5%b7%a7%e4%b8%8e%e6%8f%90%e7%a4%ba/%e6%80%8e%e6%a0%b7%e6%9b%bf%e6%8d%a2xcode%e4%b8%ad__mycompanyname__#comments</comments>
		<pubDate>Wed, 11 Nov 2009 14:07:18 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[技巧与提示]]></category>
		<category><![CDATA[Xcode]]></category>
		<category><![CDATA[提示与技巧]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=195</guid>
		<description><![CDATA[我们知道，Xcode在每个.h和.m文件头都会加上一些发行信息，如姓名，创建日期，公司名等。但公司名是用__MyCompanyName__代表，每个文件都要手工修改十分麻烦。此信息的模板存在/Library/Application Support/Apple/Developer Tools/File Templates下，格式如下：
12345678/*
&#160;* &#160;«FILENAME»
&#160;* &#160;«PROJECTNAME»
&#160;*
&#160;* &#160;Created by «FULLUSERNAME» on «DATE».
&#160;* &#160;Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved.
&#160;*
&#160;*/
我们当然可以修改此文件。但每次Xcode升级后，此信息就会丢失。我在一本有关Xcode的书中找到一个方法：
1defaults write com.apple.xcode PBXCustomTemplateMacroDefinitions '{ ORGANIZATIONNAME = &#34;Joan Smith&#34;; }'
另一种方法是通过双击~/Library/Preferences下com.apple.Xcode.plist来修改。
]]></description>
			<content:encoded><![CDATA[<p>我们知道，Xcode在每个.h和.m文件头都会加上一些发行信息，如姓名，创建日期，公司名等。但公司名是用__MyCompanyName__代表，每个文件都要手工修改十分麻烦。此信息的模板存在/Library/Application Support/Apple/Developer Tools/File Templates下，格式如下：</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 /></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: #11740a; font-style: italic;">/*<br />
&nbsp;* &nbsp;«FILENAME»<br />
&nbsp;* &nbsp;«PROJECTNAME»<br />
&nbsp;*<br />
&nbsp;* &nbsp;Created by «FULLUSERNAME» on «DATE».<br />
&nbsp;* &nbsp;Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved.<br />
&nbsp;*<br />
&nbsp;*/</span></div></td></tr></tbody></table></div>
<p>我们当然可以修改此文件。但每次Xcode升级后，此信息就会丢失。我在一本有关Xcode的书中找到一个方法：</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 /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">defaults write com.apple.xcode PBXCustomTemplateMacroDefinitions <span style="color: #bf1d1a;">'{ ORGANIZATIONNAME = &quot;Joan Smith&quot;; }'</span></div></td></tr></tbody></table></div>
<p>另一种方法是通过双击~/Library/Preferences下com.apple.Xcode.plist来修改。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e6%8a%80%e5%b7%a7%e4%b8%8e%e6%8f%90%e7%a4%ba/%e6%80%8e%e6%a0%b7%e6%9b%bf%e6%8d%a2xcode%e4%b8%ad__mycompanyname__/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>怎样在发行版中取消NSLog</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%80%8e%e6%a0%b7%e5%9c%a8%e5%8f%91%e8%a1%8c%e7%89%88%e4%b8%ad%e5%8f%96%e6%b6%88nslog</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%80%8e%e6%a0%b7%e5%9c%a8%e5%8f%91%e8%a1%8c%e7%89%88%e4%b8%ad%e5%8f%96%e6%b6%88nslog#comments</comments>
		<pubDate>Sat, 24 Jan 2009 13:22:09 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[提示与技巧]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=192</guid>
		<description><![CDATA[（注：此文已不记得出处了，作者是Fraser Hess，这里是节选翻译） 
NSLog()是一个很好的工具，它能为调试带来很大帮助。但不幸的是，它过于昂贵，特别是在iPhone上，而且根据你是怎样使用它或你用它来记录什么，它有可能泄露一些敏感和私有信息。网上有些不同的方法在发行版中去除NSLog的方法。我在这里将其汇总。

首先在Xcode中打开&#60;AppName&#62;_Prefix.pch文件，加入：
123456#ifdef DEBUG
# &#160; &#160;define DLog(...) NSLog(__VA_ARGS__)
#else
# &#160; &#160;define DLog(...) /* */
#endif
#define ALog(...) NSLog(__VA_ARGS__)
右击你的目标（target）点击 Get Info。选择 Build 一栏。将Configuration 设定为Debug。在Other C Flags 下加入-DDEBUG。
就这样。当你想在调试版下进行日志记录时使用 DLog()。而在发行版下DLog()被编译为空。使用 ALog()可在调试和发行版下进行记录。(A 代表 always。)
如果你希望用DLog替换源代码中的NSLog，这里有一个终端命令可以使用：
$ sed -i &#8220;.bak&#8221; &#8217;s/NSLog/DLog/&#8217; *.m
此命令会将所有.m文件备份为.bak。
下载：Logging Sample Application
]]></description>
			<content:encoded><![CDATA[<p>（注：此文已不记得出处了，作者是Fraser Hess，这里是节选翻译）<strong> </strong></p>
<p>NSLog()是一个很好的工具，它能为调试带来很大帮助。但不幸的是，它过于昂贵，特别是在iPhone上，而且根据你是怎样使用它或你用它来记录什么，它有可能泄露一些敏感和私有信息。网上有些不同的方法在发行版中去除NSLog的方法。我在这里将其汇总。<br />
<span id="more-192"></span><br />
首先在Xcode中打开&lt;AppName&gt;_Prefix.pch文件，加入：</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 /></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: #6e371a;">#ifdef DEBUG</span><br />
<span style="color: #6e371a;"># &nbsp; &nbsp;define DLog(...) NSLog(__VA_ARGS__)</span><br />
<span style="color: #6e371a;">#else</span><br />
<span style="color: #6e371a;"># &nbsp; &nbsp;define DLog(...) /* */</span><br />
<span style="color: #6e371a;">#endif</span><br />
<span style="color: #6e371a;">#define ALog(...) NSLog(__VA_ARGS__)</span></div></td></tr></tbody></table></div>
<p>右击你的目标（target）点击 <strong>Get Info</strong>。选择 <strong>Build</strong> 一栏。将<strong>Configuration</strong> 设定为<strong>Debug</strong>。在<strong>Other C Flags</strong> 下加入<strong>-DDEBUG。</strong></p>
<p>就这样。当你想在调试版下进行日志记录时使用 DLog()。而在发行版下DLog()被编译为空。使用 ALog()可在调试和发行版下进行记录。(A 代表 always。)</p>
<p>如果你希望用DLog替换源代码中的NSLog，这里有一个终端命令可以使用：</p>
<p><span style="font-family: monospace; font-size: xx-small;">$ sed -i &#8220;.bak&#8221; &#8217;s/NSLog/DLog/&#8217; *.m</span></p>
<p>此命令会将所有.m文件备份为.bak。</p>
<p>下载：<a href="http://www.cimgf.com/wp-content/uploads/2009/01/log.zip">Logging Sample Application</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%80%8e%e6%a0%b7%e5%9c%a8%e5%8f%91%e8%a1%8c%e7%89%88%e4%b8%ad%e5%8f%96%e6%b6%88nslog/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
