<?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>clingmarksclingmarks | some slick marks we cling to</title>
	<atom:link href="http://www.clingmarks.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.clingmarks.com</link>
	<description>some slick marks we cling to</description>
	<lastBuildDate>Sun, 06 Jan 2013 01:43:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>TaggTo &#8212; Back From A Long Journey</title>
		<link>http://www.clingmarks.com/taggto-back-from-a-long-journey/1432</link>
		<comments>http://www.clingmarks.com/taggto-back-from-a-long-journey/1432#comments</comments>
		<pubDate>Sat, 05 Jan 2013 09:37:49 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[news and announcement]]></category>
		<category><![CDATA[random thoughts]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=1432</guid>
		<description><![CDATA[This post summarized the story how our latest iPhone app, TaggTo, is created. TaggTo is an iPhone app to provide a better way to discover and share personal product experiences. It's like product reviews in an easier, more fun, and more trustworthy way.]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been almost nine months since my last post at iDevBlogADay. It&#8217;s a long time. Finally I am out of the woods and here to report my status again.</p>
<p>I started iPhone programming with my &#8220;Penguin Links&#8221; games. It was fun, and I also gained my skills of iPhone programming from it. But game programming is not really what I am good at, and neither my passion. Since late 2011, I started working on another idea.</p>
<p>I love all kinds of products. No matter something I am going to buy or not. I like to check their reviews, pictures, and different stories. My past working experience also gave me some deep knowledge about products in general. However, whenever I am reading the long, dry product reviews from Amazon or some other sites, I always ask myself, why good product reviews always have to be like Ph.D. thesis? Why can&#8217;t they be easy to write and consume, but still make their points? That&#8217;s where the idea is from: developing a new way to discover and share personal product experience. It should be easy, fun, mobile, and social.</p>
<p>I finished my first prototype iPhone app early last year. With the prototype, I was able to find two friends to work with me together on the real thing. We were also lucky to find a great designer <a href="http://firesnakelabs.com/" target="_blank">Pek Pongpaet</a> (<a href="http://www.twitter.com/pekpongpaet" target="_blank">@pekpongpaet</a>), to design the app UI. In short, it&#8217;s a long, tiring and challenging process, full of excitement and frustration. And finally, after postponing our release schedule twice, our app was sent to app store for review just before the Christmas (currently still under review due to the Christmas lock down).</p>
<div id="attachment_1435" class="wp-caption alignleft" style="width: 179px"><a href="http://www.clingmarks.com/wp-content/uploads/2013/01/Photo-12-17-12-2-17-20-PM.png"><img class="size-medium wp-image-1435 " title="News Feed Page" src="http://www.clingmarks.com/wp-content/uploads/2013/01/Photo-12-17-12-2-17-20-PM-169x300.png" alt="" width="169" height="300" /></a>
<p class="wp-caption-text">News Feed Page</p>
</div>
<div id="attachment_1436" class="wp-caption alignleft" style="width: 179px"><a href="http://www.clingmarks.com/wp-content/uploads/2013/01/Photo-12-13-12-5-23-14-PM.png"><img class="size-medium wp-image-1436 " title="Explore Page" src="http://www.clingmarks.com/wp-content/uploads/2013/01/Photo-12-13-12-5-23-14-PM-169x300.png" alt="" width="169" height="300" /></a>
<p class="wp-caption-text">Explore Page</p>
</div>
<div id="attachment_1437" class="wp-caption alignleft" style="width: 179px"><a href="http://www.clingmarks.com/wp-content/uploads/2013/01/Photo-12-9-12-4-29-48-PM.png"><img class="size-medium wp-image-1437 " title="Activity Page" src="http://www.clingmarks.com/wp-content/uploads/2013/01/Photo-12-9-12-4-29-48-PM-169x300.png" alt="" width="169" height="300" /></a>
<p class="wp-caption-text">Activity Page</p>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p style="text-align: center;"><em><span style="font-size: 13px; text-align: center;">(Screenshots of TaggTo iPhone App)</span></em></p>
<p>The app is called &#8220;TaggTo&#8221;, because we use &#8220;tagg&#8221;s to let users mark their comments on product pictures, at the spot where they are talking about. This makes each comment short, precise, and always in context of pictures. Hence better for creation and consumption from mobile devices. We also added the social factor &#8212; users can follow their facebook friends, or any users they trust. In their &#8220;News Feed&#8221; section, they can see all recent &#8220;taggs&#8221; from their followed users. By putting all these together, we want to make the app not only a place for seeking opinions on products, but also entertaining by looking at all kinds of product pictures and learning what your friends are up to.</p>
<p>We created a new website for the app: <strong><a href="http://www.taggto.com" target="_blank">www.taggto.com</a></strong>. You can also download our app (we got an enterprise license) directly from our site: <strong><a href="http://www.taggto.com/beta/" target="_blank">www.taggto.com/beta/</a></strong>. And the best part is, we are running a<strong> free iPad Mini promotion</strong> now. You can get a chance to win the iPad Mini by writing just five taggs. For more details, <a href="http://www.taggto.com/views/ipad-mini.htm" target="_blank">please check our our site</a>. <span style="font-size: 13px;">Please download the app and give it a try. We love to know what you think! And good luck with the iPad Mini!</span></p>
<p>Finally, let me list the technologies we used in this project. After all, this is a developer&#8217;s blog, isn&#8217;t it?</p>
<p>iPhone App:</p>
<ul>
<li><a href="http://www.crittercism.com/" target="_blank">Crittercism</a>: for tracking crashes</li>
<li><a href="http://www.flurry.com/" target="_blank">Flurry</a>: for app analytics</li>
<li><a href="https://github.com/johnezang/JSONKit" target="_blank">JSONKit</a>: for json creation and parsing</li>
<li><a href="https://github.com/magicalpanda/MagicalRecord" target="_blank">MagicalRecord</a>: for Core Data</li>
<li><a href="https://github.com/jverkoey/nimbus" target="_blank">Nimbus</a>: general framework, replacing the old Three20.</li>
<li><a href="http://zbar.sourceforge.net/iphone/index.html" target="_blank">ZBar</a>: for barcode scanning</li>
<li>And many other open source UI components</li>
</ul>
<div>Backend</div>
<div>
<ul>
<li>Jetty: application server</li>
<li>MySQL: database</li>
<li>Nginx: web server</li>
<li>Redis: social logic and cache</li>
<li>SOLR: product search</li>
<li>RabbitMQ: message queue</li>
<li>Language: Java and Python</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/taggto-back-from-a-long-journey/1432/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Three20 Network Programming ( 1 )</title>
		<link>http://www.clingmarks.com/three20-network-programming-1/1389</link>
		<comments>http://www.clingmarks.com/three20-network-programming-1/1389#comments</comments>
		<pubDate>Fri, 09 Mar 2012 05:38:08 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iOS programming]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[iphone programming]]></category>
		<category><![CDATA[three20]]></category>
		<category><![CDATA[TTURLRequest]]></category>
		<category><![CDATA[TTURLRequestDelegate]]></category>
		<category><![CDATA[TTURLResponse]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=1389</guid>
		<description><![CDATA[An easy to follow tutorial goes through all the details about how to do networking programming for your iOS/iPhone project, by leveraging the power of the Three20 framework.]]></description>
			<content:encoded><![CDATA[<p>I have been off &#8220;iDevBlogADay&#8221; for a while, because I was really busy recently. I am on a project with a much bigger scope than my iPhone games. I have to dedicate as much time as I can. Finally, I am glad I am ready to share something I have learned in my project in past several months.</p>
<p>Actually, I think the title of this blog is a little off. It doesn&#8217;t involve anything like socket or TCP/UDP. Be more precisely, it&#8217;s a tutorial about how to do web requests by using Three20 framework. My assumption is you already know the basics of the Three20 framework. You can find more details at: <a href="http://three20.info/" target="_blank">http://three20.info</a>. But if you don&#8217;t know anything about Three20 yet, don&#8217;t be scared. This tutorial actually doesn&#8217;t involve much Three20 specific stuff.</p>
<p>No matter you are programming on a iOS game or an application, a common task is to initiate an HTTP request to a web server, and download / upload some information from / to it. It can be done by just using Apple&#8217;s iOS framework, but it&#8217;s quite tedious. You have to handle all the hairy details of every step. One great alternative is to use &#8220;<a href="http://allseeing-i.com/ASIHTTPRequest/" target="_blank">ASIHTTPRequest</a>&#8221; &#8212; an open source framework created by Ben Copsey. But if you are using Three20 framework in your project already, you don&#8217;t have to add this one extra framework. Three20 already provides very solid support to manage web requests.</p>
<p>There are several different kinds of HTTP requests, such as HEAD, OPTION, PUT, &#8230; But the most used ones are GET and POST. GET is used for downloading information, and POST can be used to upload information. These two methods will be the focus of this tutorial.</p>
<p>No matter you want to download or upload content, the first thing you need to do is to initiate a web request. To do that in Three20&#8242;s world, three classes/protocols are the keys. These classes are: <code>TTURLRequest</code> class, <code>TTURLRequestDelegate</code> protocol, and <code>TTURLResponse</code> protocol. Now let&#8217;s look at a really simple example first:</p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;">TTURLRequest <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>TTURLRequest requestWithURL<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.google.com/robots.txt&quot;</span> delegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
request.httpMethod <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GET&quot;</span>;
request.response <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TTURLResponse alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Send the request</span>
<span style="color: #002200;">&#91;</span>request send<span style="color: #002200;">&#93;</span>;</pre>
</td>
</tr>
</table>
</div>
<p>You probably can guess from the code, &#8212; yes, we are trying to download Google&#8217;s &#8220;robots.txt&#8221; file. To achieve that, we have to create a TTURLRequest object first in line #1, at the same time assign a delegate object; and then in line #3, we created TTURLResponse object to handle the web response.</p>
<h3>TTURLRequest</h3>
<p>In above example, line #1 shows the most easy way to create a TTURLRequest object, which is responsible for constructing an HTTP request based on parameters you passed in, sending the request to the web server, and then handle the control to the TTURLResponse object. A few things that need your attention in this process:</p>
<ul>
<li><strong>Send request:</strong> there are two ways to send out a request: asynchronous or synchronous. By default, when you call <code>[request send]</code>, the request will be sent out asynchronously. Or you can use <code>[request sendSynchronously]</code> to make the call blocking.</li>
<li><strong>Time out:</strong> this is a really important parameter but usually got ignored. The default time out for a TTURLRequest is 5 mins, which is quite long. You can change the time out like this:<br/>
<p><code>request.timeoutInterval = 15.0f; // in seconds</code><br/><br />
Remember to use the latest Three20 framework. In earlier versions this property was not there.</li>
<li><strong>Max download size:</strong> by default, Three20 has an arbitrary limit for the size of data you can download for each request: 150k. If you are going to download more data in the request, the limit can be removed by calling:<br/><br />
<code>[[TTURLRequestQueue mainQueue] setMaxContentLength:0];</code><br/><br />
Personally I think it&#8217;s always a good idea to remove the limit (or set it to a much higher value), &#8217;cause 150K is really nothing on today&#8217;s Internet. For now, don&#8217;t worry about the <code>TTURLRequestQueue</code> class. We&#8217;ll come back to it in the second part of the tutorial.</li>
<li><strong>Reporting progress:</strong> <code>TTURLRequest</code> class provides several convenient properties for the caller object to monitor the progress of the request, which are:
<ul>
<li><code>totalBytesDownloaded</code></li>
<li><code>totalBytesExpected</code></li>
<li><code>totalBytesLoaded</code> (if this request is for uploading content)</li>
<li><code>isLoading</code>: whether or not the current request is activeWith the help of these properties, you can easily create a download progress bar in the delegate callback method. We will revisit this later in next section.</li>
</ul>
</li>
<li><strong>HTTP headers:</strong> HTTP headers are essentially key value pairs. For example, when you have multiple async HTTP calls at the same time, it&#8217;s hard to tell which one comes back first. In this case, you can use the &#8220;ETag&#8221; HTTP header to identify each of them:</br><br />
<code>[request.headers setObject:@"firstRequest" forKey:@"ETag"];</code></br><br />
And then in the delegate callback, you just need to check the &#8220;ETag&#8221; header to identify each request. Please note that Three20 API already extracted some commonly used HTTP headers into properties, such as &#8220;contentType&#8221;. So before you set the header value, make sure to check if it&#8217;s already part of the request&#8217;s properties.
</li>
<li><strong>HTTP method:</strong> In our example above, the HTTP method is set in line #2. The most used two HTTP methods are GET and POST. Usually GET is for downloading, and POST is for uploading.</li>
<li><strong>Last but not least, remember to encode your parameters before you create the TTURLRequest object.</strong> For example, if your URL is &#8220;http://www.google.com/search?q=apple&#8217;s latest ipad&#8221;, it needs to be encoded into: &#8220;https://www.google.com/search?q=apple&#8217;s%20latest%20ipad&#8221;. For how to encode/decode an URL, please check out <a href="http://stackoverflow.com/questions/6688287/url-decoding-encoding-nsstring" target="_blank">this post on stackoverflow.com</a>.</li>
</ul>
<h3>TTURLRequestDelegate</h3>
<p>The delegate object is the place to implement some real business logics. All methods defined in this protocol is optional, but usually you want to implement at least two methods:</p>
<p><code>- (void)requestDidFinishLoad:(TTURLRequest*)request</code> &#8212; this delegate method is called when the request has finished successfully.<br />
<code>- (void)request:(TTURLRequest*)request didFailLoadWithError:(NSError*)error</code> &#8212; this one is called the request has failed. An error message is sent back along with the original TTURLRequest object.</p>
<p><code>TTURLRequestDelegate</code> is a very important protocol in Three20 framework. You can see it in almost all web request related classes. For example, <code>TTImageView</code>, a view to display image in Three20&#8242;s flavor, also implemented the <code>TTURLRequestDelegate</code>. That&#8217;s because <code>TTImageView</code> is capable of displaying an image by downloading it from web directly. So it has to implement the <code>TTURLRequestDelegate</code> to handle the HTTP request.</p>
<p>Besides above two methods, other methods also provide some useful information. For example, in previous section we mentioned using <code>TTURLRequest's</code> several properties to monitor the progress of the request. That can be done in the delegate method <code>requestDidUploadData</code>:</p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>requestDidUploadData<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TTURLRequest <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>request <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">float</span> progress <span style="color: #002200;">=</span> request.totalBytesLoaded <span style="color: #002200;">/</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">float</span><span style="color: #002200;">&#41;</span>request.totalBytesExpected;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Current progress: %f&quot;</span>, progress<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre>
</td>
</tr>
</table>
</div>
<h3>TTURLResponse</h3>
<p>TTURLResponse is the last pice of the puzzle of Three20 network programming. It is actually a protocol with two methods defined:</p>
<p><code>- (NSError *)request:(TTURLRequest *)request processResponse:(NSHTTPURLResponse *)response data:(id)data</code><br />
<code>- (NSError *)request:(TTURLRequest *)request processErrorResponse:(NSHTTPURLResponse *)response data:(id)data</code></p>
<p>The first one is for processing response data from a successful request, and the second one is for a failed request. You can implement your own TTURLResponse instance to handle the response, but in most cases, the provided four classes in Three20 framework should be sufficient.</p>
<ul>
<li><strong><code>TTURLDataResponse</code></strong>: This is the most straightforward one. If you look at the source code of this class, it just simply save the data from the response to its internal readonly property &#8220;data&#8221;, and then you can use the data to do whatever you want. For example, you can convert the data to a NSString:
<p><code>NSString* str = [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding];</code>
</li>
<li><strong><code>TTURLImageResponse</code></strong>: <code>TTURLImageResponse</code> is similar to the <code>TTURLDataResponse</code>. The only extra work it does is trying to convert the data to an UIImage object, and save it to the internal readonly property &#8220;image&#8221;. This class is used especially less often because the <code>TTImageView</code> class also provides the same functionality to download images from web, and is more capsulated comparing to the <code>TTURLImageResponse</code> class.</li>
</ul>
<ul>
<li><strong><code>TTURLJSONResponse</code> and <code>TTURLXMLResponse</code></strong>: I am going to talk about these two classes together because they are really similar to each other. Both are often used for API calls; both handle data in tree structures and have a root object; both already have a parser built-in. In the implementation of <code>- (NSError *)request:(TTURLRequest *)request processResponse:(NSHTTPURLResponse *)response data:(id)data</code>, the built-in parser will try to parse the data into a root object. Depending on the structure of the JSON/XML, it could be a NSArray, or a NSDictionary. So you need to a test it before you start processing the parsing result, something like:
<p><code>TTDASSERT([response.rootObject isKindOfClass:[NSDictionary class]]);</code></p>
<p>Another caveat is how to convert your object to JSON string so that it can be sent through an HTTP request. The JSON framework used in Three20 is <a href="http://stig.github.com/json-framework/" target="_blank">SBJSON</a>. It already knows how to convert a collection to a JSON string. But to convert your own class to a JSON string, you have to implement the &#8220;<code>- (id) proxyForJson</code>&#8221; method. This method must return a type that SBJSON already knows how to handle &#8212; for example, most of the cases you can just convert your object to a NSDictionary. Or you can also just return a NSString if you like.</li>
</ul>
<p>So far we have covered most of the basic stuff in Three20 network programming. You should have a good idea about how to work with HTTP GET method now. Since one of Three20&#8242;s biggest problems is lack of documentation, I hope this tutorial can make this part easier for you. Before I finish this post, do you mind doing a homework? <img src='http://www.clingmarks.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  I always believe you will learn more when you actually get your hands dirty. The task is simple: </p>
<p><strong>use Three20 framework to download the content from this URL:</strong></p>
<p><a href="http://www.flickr.com/services/rest/?method=flickr.test.echo&amp;format=json&amp;api_key=0aaaec5a4450a7db6a939e38bf768eed" target="_blank">http://www.flickr.com/services/rest/?method=flickr.test.echo&amp;format=json&amp;api_key=0aaaec5a4450a7db6a939e38bf768eed</a></p>
<p><strong>and then parse the response into a NSDictionary.</strong></p>
<p>In the next post, I&#8217;ll talk about more advanced network programming such as uploading a big file, and some neat tricks. Stay tuned.</p>
<h3>References</h3>
<ul>
<li>Three20 Framework: <a href="http://three20.info/" target="_blank">http://three20.info/</a></li>
<li>Three20 Framework API Doc: <a href="http://facebook.github.com/three20/api/index.html" target="_blank">http://facebook.github.com/three20/api/index.html</a></li>
<li>ASIHTTPRequest: <a href="http://allseeing-i.com/ASIHTTPRequest" target="_blank">http://allseeing-i.com/ASIHTTPRequest</a>/</li>
<li>How to encode/decode an URL: <a href="http://stackoverflow.com/questions/6688287/url-decoding-encoding-nsstring" target="_blank">http://stackoverflow.com/questions/6688287/url-decoding-encoding-nsstring</a></li>
<li>SBJSON:<a href="http://stig.github.com/json-framework/" target="_blank">http://stig.github.com/json-framework</a></li>
<li>HTTP Methods: <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html" target="_blank">http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html</a></li>
<li>HTTP Headers: <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html" target="_blank">http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html</a></li>
<li>JSON Data Format: <a href="http://www.json.org/" target="_blank">http://www.json.org/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/three20-network-programming-1/1389/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>iOS App Free Promotion, Chinese App Market, and Grand Canyon</title>
		<link>http://www.clingmarks.com/ios-app-free-promotion-chinese-app-market-and-grand-canyon/1365</link>
		<comments>http://www.clingmarks.com/ios-app-free-promotion-chinese-app-market-and-grand-canyon/1365#comments</comments>
		<pubDate>Thu, 29 Dec 2011 00:59:29 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[random thoughts]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[china]]></category>
		<category><![CDATA[chinese app market]]></category>
		<category><![CDATA[free promotion]]></category>
		<category><![CDATA[ios apps promotion technique]]></category>
		<category><![CDATA[iOS programming]]></category>
		<category><![CDATA[iphone apps]]></category>
		<category><![CDATA[iphone games]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=1365</guid>
		<description><![CDATA[Last week, I ran a free promotion on my iOS game "PenguinLinks Pro 2", and have learned a lot from this process. This blog post shares some numbers from this promotion, and my thoughts on how effective the "free promotion" is in general. It also discussed the growth of Chinese app market. ]]></description>
			<content:encoded><![CDATA[<p><span class="dropcap2">E</span>arly this year, after I quit my job and started my indie developer life, I spent quite some time working on my iPhone game &#8220;PenguinLinks 2&#8243;. However, even though I have tried my best to tweak the UI, enhance the game logics, it has never been as successful as I hoped for. Even in China (it is a popular game category there), it is just OK at most &#8212; hardly beats its previous version &#8220;PenguinLinks&#8221;, which  has a much rougher UI than the new version.</p>
<p>In the second half of the year, I shifted my focus to another iPhone apps (not game), which I think I am better at. However, I am still curious about how far my PenguinLinks games can go if they can have some exposure. Nowadays, the most used iOS app promotion technique is probably &#8220;Free Promotion&#8221;. So I asked several companies in this business, including FreeAppADay, FreeAppParty and a few others. Their offers are from $4000 to $18K per promotion, and usually guarantee top 25 in Game category. Some of them also offer performance based charge, usually $1 per install &#8212; please note this is actually a much more expensive one: your app can easily get tens of thousands of downloads when it becomes free, which means you need to pay $1 for each download to the promotion provider. It&#8217;s like a no-limit hold&#8217;em game.</p>
<h3>The Free Promotion</h3>
<p>To me, all the options are too expensive. Most importantly, I am not 100% sure how much it can help, specially once my game goes back to paid. So I decided to run a free promotion by myself. Here are what I have done and the result:</p>
<ul>
<li>On 12/18, I released version 2.6, with the fix of a few bugs, and also let the game pick up some momentum.</li>
<li><strong>On 12/22 12AM, my paid game &#8220;<a href="http://itunes.apple.com/app/penguinlinks-pro-2/id449071212?mt=8" target="_blank">PenguinLinks Pro 2</a>&#8221; went free.</strong></li>
<li>I twitted it, and also posted the news on my facebook page: <a href="http://www.facebook.com/clingmarks" target="_blank">http://www.facebook.com/clingmarks</a>, which has almost 1000 fans.</li>
<li>In the following several days, the news got twitted 25 times on twitter, 17 times on weibo.com (twitter like service in China).</li>
<li><strong><a href="http://www.techbargains.com/news_displayItem.cfm/280277" target="_blank">The news was also picked up by techbargains.com on 12/22 (see screenshot bellow).</a></strong> I don&#8217;t know how many downloads this has contributed, but it&#8217;s certainly fun to see my game mentioned on one of the most popular tech deal sites.<br />
<a href="http://www.clingmarks.com/wp-content/uploads/2011/12/iPhone-App-Roundup-PenguinLinks-Pro-2-FREE-LogMeIn-FREE-.jpg"><img class="alignnone" src="http://www.clingmarks.com/wp-content/uploads/2011/12/iPhone-App-Roundup-PenguinLinks-Pro-2-FREE-LogMeIn-FREE-.jpg" alt="" width="755" height="302" /></a></li>
<li><strong>Results:</strong></li>
<ul>
<li>On the first day of the promotion, the rank of my game &#8220;PenguinLinks Pro 2&#8243; went up dramatically in most countries:</li>
<ul>
<li><strong>US: 28 in Board, 45 in Family, which is the best it ever achieved.</strong></li>
<li><strong>China: 2 in Board, 3 in Family, 25 in Games, 71 Overall &#8212; this was achieved a few days later, actually today, 12/28.</strong></li>
</ul>
<li><strong>On the first day of promotin, it received 12.5K downloads total: China &#8212; 8.7K, US &#8212; 2.4K.</strong></li>
<li>In the following days of the promotion, downloads from China grow gradually to about 10K and stay there; downloads from all other countries have dropped significantly comparing to day one.</li>
<li>The reviews for the game has been very positive:</li>
<ul>
<li>US: 20 ratings, 4.5 on average;</li>
<li>China: 272 ratings, 4.5 on average.</li>
</ul>
</ul>
</ul>
<p>Before the promotion, my goal was pushing my game to top 25 in one category in US, and top 25 in Games in China. As of today, it has reached the goal in China, but nowhere near the goal in US. But I am still pretty happy about the result. What I have learned from this promotion are:</p>
<ul>
<li><strong>Quality is the ultimate factor of success.</strong> You can push an app up to the top, but only apps with great quality stay. Ranks of most the apps will drop like a rock once promotions end. Remember this is just a chance to show, and it doesn&#8217;t convert to success directly.</li>
<li>You can run a &#8220;test&#8221; free promotion like mine just by yourself. <strong>Many services, websites are monitoring price drops in Apple App Store. By making a paid app free, you will naturally gain a lot of free exposures.</strong> It will give you a better sense about how far your app can go; and from user feedbacks, you will know what to improve next.</li>
<li>Are all kinds of expensive-for-developers free promotions really worth it? <strong>It all depends on the quality of your app.</strong> All the promotions can give you is short time exposures. To stay there, your app must have high quality.</li>
<li>Last but not least, different markets have different needs. That&#8217;s what I am going to talk about next &#8211;</li>
</ul>
<h3>Chinese App Market</h3>
<p>A few days ago, I read an article on <a href="http://techcrunch.com/2011/12/20/distimos-year-end-report-shows-why-developers-love-ios-iphone-4x-android-revenue-ipad-2x/" target="_blank">Techcrunch</a>. It mentioned that:</p>
<blockquote><p>In January, China generated only 18% of the downloads when comparing the U.S. iPhone App Store together with China’s. By November, it was generating 30% of the combined total downloads. And on the iPad, the two stores are almost equal in size in terms of downloads.</p></blockquote>
<p>I totally felt it in this free promotion.</p>
<p>In August 2010, the first version of my game &#8220;PenguinLinks Free&#8221; become #2 overall app in the whole app store in China, and stayed there for about a week. At that time, it had about 8K to 10K download per day. 16 months later, with about the same amount of downloads, my game is only #25 in Games, #71 in Overall. #71 to #2, that&#8217;s a huge difference. I don&#8217;t know how many more downloads it takes to get to #2 overall today. But if somebody tells me it needs a few hundreds of thousand, I won&#8217;t be surprised. Just from this one small case, you can see how much the Chinese app market has grown in last 16 months.</p>
<p>Apple also sees the opportunity there. Recently, <a href="a &quot;test&quot; free promotion will give you a better sense about how far your app can go; and from user feedbacks, you will know what to improve next." target="_blank">Apple just started accepting the local currency in China</a>. Also, credit card is not a required payment method anymore in App Store China, since most people there don&#8217;t have a credit card capable of foreign transactions. Apple also added a way to pay by cellphone, which is popular in China, Japan and South Korean. All these are important steps to attract more paid customers there. In the next several years, with the introduction of the new iOS devices, this market will grow even bigger, with no doubt.</p>
<h3>Grand Canyon</h3>
<p>My free promotion started on 12/22, just a few hours before the iTunes Connect locked down. And then, on 12/23, I went to Grand Canyon for a vacation. Yes, it&#8217;s cold there. But the stunning view is well worth it. As an indie developer, vacations is as needed as any other career. So take advantage this holiday season, go out, enjoy. And come back refreshed, with more energy and ideas.</p>
<p style="text-align: center;"><a href="http://www.clingmarks.com/wp-content/uploads/2011/12/panorama-1024x199.jpg"><img class="size-large wp-image-1371 aligncenter" title="Grand Canyon" src="http://www.clingmarks.com/wp-content/uploads/2011/12/panorama-1024x199.jpg" alt="" width="819" height="159" /></a></p>
<p>And finally, I plan to end my free promotion tomorrow morning. So if you are interested, don&#8217;t miss this opportunity. <strong><a href="http://itunes.apple.com/app/penguinlinks-pro-2/id449071212?mt=8" target="_blank">Grab it.</a></strong> You may like it. Who knows? <img src='http://www.clingmarks.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/ios-app-free-promotion-chinese-app-market-and-grand-canyon/1365/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>clingmarks.com just had a major face-lift</title>
		<link>http://www.clingmarks.com/clingmarks-com-just-had-a-major-face-lift/1329</link>
		<comments>http://www.clingmarks.com/clingmarks-com-just-had-a-major-face-lift/1329#comments</comments>
		<pubDate>Mon, 05 Dec 2011 19:40:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[news and announcement]]></category>
		<category><![CDATA[random thoughts]]></category>
		<category><![CDATA[clingmarks]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[theme]]></category>
		<category><![CDATA[website design]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=1329</guid>
		<description><![CDATA[This blog was started back in 2007 (it was not under clingmarks.com domain at that time). From day one, it uses just some very basic wordpress themes. When we had more and more games, we started to think migrating this site to a more professional looking one. But for various reasons, this project had never been on the top of our to-do list.

Last week, finally I decided to do it.]]></description>
			<content:encoded><![CDATA[<p>We have wanted to do this for a long time. But for for all kinds of reasons, it had never been done. Until last week.</p>
<p>This blog was started back in 2007 (it was not under clingmarks.com domain at that time). From day one, it uses just some very basic wordpress themes. When we had more and more games, we started to think migrating this site to a more professional looking one. But for various reasons, this project had never been on the top of our to-do list.</p>
<p>Last week, finally I decided to do it. My goals are:</p>
<ul>
<li>A more professional looking site</li>
<li>Make it a showcase of our products</li>
<li>Prettier blog post, with better SEO support</li>
<li>Fully integrated with Facebook, Twitter and Google+</li>
</ul>
<p>With our objectives set, we purchased a professional theme for business, and hoped that we just needed to apply it, and everything would be done. But it&#8217;s not that simple. The theme is not as flexible as we want, and we also have some specific requests. It actually took me almost a week to work everything out, with the help from the tech support from the theme creator.</p>
<p>On Friday night, we finally figured out all the issues and pushed site to live. The end result is what you are seeing now. I think it&#8217;s day and night comparing to our original site. I am very satisfied &#8212; just check out this before-and-after here:</p>
<div class="row">
<div class="col col_1_2 ">
<div class="inner">
<a href="http://www.clingmarks.com/wp-content/uploads/2011/12/clingmarks-before.jpg" class="frame_box" style="color:" rel="prettyPhoto[p_667]" title="clingmarks.com before" class="prettyPhoto"><br />
<img src="http://www.clingmarks.com/wp-content/uploads/2011/12/clingmarks-before.jpg" width="250" alt=""><br />
</a>
</div>
</div>
<div class="col col_1_2 ">
<div class="inner">
<a href="http://www.clingmarks.com/wp-content/uploads/2011/12/clingmarks-after.jpg" class="frame_box" style="color:" rel="prettyPhoto[p_343]" title="clingmarks.com after" class="prettyPhoto"><br />
<img src="http://www.clingmarks.com/wp-content/uploads/2011/12/clingmarks-after.jpg" width="250" alt=""><br />
</a>
</div>
</div>
</div>
<p>Being indie developers is really our passion. That&#8217;s what I wrote in the &#8220;About Us&#8221; page. I am going to quote that page to end this post.</p>
<blockquote><p>We started by introducing the Penguin Links game on Android Marketplace in March 2009. And it was called “Pair Up”. We did not expect much. The whole practice was really just an Android exercise. However, just a few hours after the initial release, we got the first review! I still remember the excitement we had when we saw that. The first version was very rough, as you can imagine. But users’ feedbacks helped us to get better and better. And a few months later, the “Pair Up” game had become one of the top games in puzzle category, and stayed there for a long time. In last almost three years, this game had more than half million downloads, and thousands of reviews.</br></br></p>
<p>At the meantime, we were also working on an iPhone apps, which took longer than we thought. In June 2010, PenguinLinks for iOS was released. However, at that time, the competition at App Store was already very strong, and the games didn’t do as well as we expected. But things changed in the middle of August, 2010. One day when I took out my iPhone to check the number of downloads, I was surprised to see the it has more than doubled from the previous day. But I thought it could be something random. The day after, it doubled again. And tripled again after another day. I knew it must be something big. I checked the downloads by country and found most of them were from China. Then I opened the App Store for China, and saw our game “PenguinLinks Free” was already No. 2 app in the whole app store! Not in one category, not in games, but the whole app store! Our server was so busy (since there was no game center yet at that time, we used our own server to host score board) in those days that it almost crashed. What a fun!</br></br></p>
<p>Be frankly, our games were never a big success, such as Angry Bird, Tiny Wings, Jewellust, … But we have enjoyed doing this as much as anybody. The feeling of building something actually used by somebody, loved by somebody, or even criticized by somebody, is just awesome.</br></br></p>
<p>We are still working on these projects, on and off — since these are not our fulltime jobs. We may stop working on them someday. But we have had a lot of fun by building this. And hopefully we have brought some fun to our users.</br></br></p>
<p>At the meantime, if you want to know more about our products, check out the product page. You can also follow us on Facebook or twitter (please see the footer of this site). Email is always welcome, too. Just drop a line to: support [at] clingmark.com, we’ll get you back.</br></br></p>
<p>And finally, thank you ALL for reading this blog, playing our games, leaving feedbacks, … It’s YOU who drives us this far. And we really appreciate that.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/clingmarks-com-just-had-a-major-face-lift/1329/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Setup sub domain on another server machine</title>
		<link>http://www.clingmarks.com/setup-sub-domain-on-another-server-machine/942</link>
		<comments>http://www.clingmarks.com/setup-sub-domain-on-another-server-machine/942#comments</comments>
		<pubDate>Wed, 30 Nov 2011 04:43:06 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[linux and servers]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[reverse proxy]]></category>
		<category><![CDATA[route]]></category>
		<category><![CDATA[sub domain]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[virtual host]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=942</guid>
		<description><![CDATA[Recently I am working on migrating our site to a new theme (you can see why, don't you?) So I setup an apache instance on our test server, and try to apply the new theme there first. It's not a very straightforward task. I often need help from the vendor's tech support. But sometime even the support guy couldn't tell what went wrong just based on my description. The best way for him to debug is, logging into my test server's web console, and checking things from there. This needs to expose my internal test server to outside traffic.]]></description>
			<content:encoded><![CDATA[<p>Recently I am working on migrating our site to a new theme (you can see why, don&#8217;t you?) So I setup an apache instance on our test server, and try to apply the new theme there first. It&#8217;s not a very straightforward task. I often need help from the vendor&#8217;s tech support. But sometime even the support guy couldn&#8217;t tell what went wrong just based on my description. The best way for him to debug is, logging into my test server&#8217;s web console, and checking things from there. This needs to expose my internal test server to outside traffic.</p>
<p>To abstract things a bit, what I need to do is, use my production apache server to route the internet traffic based on the request&#8217;s domain name: if it&#8217;s for the test sub domain, forward to the test server; otherwise serve it locally.</p>
<p>To achieve that, the production apache server needs to act like a proxy server. To change its behavior, I just need to modify the production server&#8217;s configuration file at path (on ubuntu server):</p>
<div class="wp_syntax">
<div class="code">
<pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>apache2<span style="color: #000000; font-weight: bold;">/</span>sites-available<span style="color: #000000; font-weight: bold;">/</span>clingmarks.com.conf</pre>
</div>
</div>
<p>All I need to do is to add this section to the end of the original configuration file (the sub domain for my test server is test.clingmarks.com, with IP address 192.168.2.5):</p>
<div class="wp_syntax">
<div class="code">
<pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;VirtualHost</span> *<span style="color: #000000; font-weight: bold;">&gt;</span></span>
    ServerName test.clingmarks.com
    ProxyPass / http://192.168.2.5/
    ProxyPassReverse / http://192.168.2.5/
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/VirtualHost<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre>
</div>
</div>
<p>Of course, I also need to add a DNS entry for my sub domain to my domain name registrar, to point to the same IP address as main main domain.</p>
<p>After these changes, the support guy is able to log in my test server from address http://test.clingmarks.com . </p>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/setup-sub-domain-on-another-server-machine/942/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Custom Mac Mechanical Keyboard &#8212; Let&#8217;s have some fun!</title>
		<link>http://www.clingmarks.com/custom-mac-mechanical-keyboard-lets-have-some-fun/893</link>
		<comments>http://www.clingmarks.com/custom-mac-mechanical-keyboard-lets-have-some-fun/893#comments</comments>
		<pubDate>Wed, 23 Nov 2011 15:24:55 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[hardware and gadgets]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[cherry switch]]></category>
		<category><![CDATA[custom mac key caps]]></category>
		<category><![CDATA[das keyboard]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[keyboard mod]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[matias]]></category>
		<category><![CDATA[matias tactile pro]]></category>
		<category><![CDATA[mechanical keyboard]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=893</guid>
		<description><![CDATA[Since I started playing with mechanical keyboards a few months ago, I was totally amazed by how satisfying they feels. I couldn't even believe I have been stucked with membrane keyboards (regular keyboards) for so long! However, I am a mac user. Since the day I fell in love with mechanical keyboards, I started the search for a mac compatible one. Sure, most of the keyboards do work on mac, but I think what I am looking for is a keyboard not only "working", but also having mac's look and feel. Which is hard.

The closest match is the <a href="http://matias.ca/tactilepro3/" target="_blank">Matias Tactile Pro 3</a>. It's a beautiful keyboard]]></description>
			<content:encoded><![CDATA[<p>Since I started playing with mechanical keyboards a few months ago, I was totally amazed by how satisfying they feels. I couldn&#8217;t even believe I have been stucked with membrane keyboards (regular keyboards) for so long! However, I am a mac user. Since the day I fell in love with mechanical keyboards, I started the search for a mac compatible one. Sure, most of the keyboards do work on mac, but I think what I am looking for is a keyboard not only &#8220;working&#8221;, but also having mac&#8217;s look and feel. Which is hard.</p>
<p>The closest match is the <a href="http://matias.ca/tactilepro3/" target="_blank">Matias Tactile Pro 3</a>. It&#8217;s a beautiful keyboard that looks just like the original Apple Extended Keyboard. And it&#8217;s completely mac compatible (of course). However, the key switches it uses are ALPS, which is stronger than cherry blue switch &#8212; the switch I preferred. So I finally give it up. I kept trying keyboards with different brands, and eventually settled with a <a href="http://www.daskeyboard.com/" target="_blank">DAS keyboard Model S</a>. I know it&#8217;s not a mac keyboard, but I like its simple looking, the overall quality (see my P.S. at the end of the post for another story), and the relatively low price (still more expensive than membrane keyboards, though). And it works fine with my mac. But sometime, I still hope that one day, I can find a keyboard I love, with the authentic mac keyboards&#8217; look and feel.</p>
<div class="wp-caption alignnone" style="width: 514px"><img class="     " title="DAS Model S Professional Keyboard" src="http://www.daskeyboard.com/images/products/pro/2.jpg" alt="" width="504" height="251" />
<p class="wp-caption-text">DAS Model S Professional Keyboard</p>
</div>
<p>Until I found this post on geekhack.org &#8212; an online community for geeks with love for keyboards: <a href="http://geekhack.org/showthread.php?23203-Finishing-Touches-for-a-Layout" target="_blank">http://geekhack.org/showthread.php?23203-Finishing-Touches-for-a-Layout</a>.</p>
<p>The original author, iindigo,  is a genius. He designed a wonderful mac keyboard layout to match exactly the look of the original mac keyboard. All the font, position of each character, are carefully designed so that they look just like the Apple mac keyboard. Then, based on this layout, a set of custom key caps can be ordered to replace the original ones &#8212; a big benefit of using mechanical keyboards is that all the key caps are replaceable &#8212; to make the keyboard a lot more mac-looking.</p>
<p>And the best part is, iindigo is general enough to share his work with everybody, for free!</p>
<p>So I asked him to send me the layout file. And then I added a few extras based on the layout of <a href="http://store.apple.com/us/product/MB110LL/B" target="_blank">the current Apple keyboard</a>. The additional changes are:</p>
<ul>
<li>Multimedia symbols on F1-F15.</li>
<li>Change the original &#8220;menu&#8221; key to a apple logo key &#8212; which will be the &#8220;Fn&#8221; key. I also make it the only black key to give the whole keyboard a little kick.</li>
<li>Right-align the right &#8220;control&#8221; key.</li>
<li>And just for fun, I added a &#8220;pig king&#8221; from Angry Bird to the space bar! <img src='http://www.clingmarks.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> </li>
</ul>
<p>I submitted an order for the custom key caps on <a href="http://www.wasdkeyboards.com" target="_blank">www.wasdkeyboards.com</a>, a website that specializes in custom keyboards, and keyboard parts. After just a day, I was told the key caps were ready to pick up (yes, I am luck enough to be close to them). WASD keyboards was also kind enough to offer me to change all the keys in their office, so that I can use their wire key cap puller &#8212; just to make things easier.</p>
<p>When I walked into WASD Keyboards&#8217; office, my key caps are already there, nicely laid out on a table, just like on a keyboard:</p>
<p style="text-align: center;"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_keycaps.jpg"><img class="size-large wp-image-899 aligncenter" title="keyboard2_keycaps" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_keycaps-1024x355.jpg" alt="" width="574" height="198" /></a></p>
<p style="text-align: left;">At the first look, I was a little worried that the letters seemed a bit too thin, and not dark enough on the keys. But overall, the laser etched letters/symbols are very crisp, and look nice on the white key caps. WASD&#8217;s staffs were very nice, too. Not only they let me do the key switching in their office, they also showed me how to lubricate the stabilizers of the bigger keys (this is my first time changing all the keys of a mechanical keyboard). The whole thing turned out a little longer than I thought. But once it was finished, I was really amazed by the overall look of this &#8220;new&#8221; keyboard. The font is perfect, not thin at all; the white key caps on the black base provide a great contrast. It just looks beautiful!</p>
<p style="text-align: left;">Once I got back to home, I created a custom configuration file for <a href="http://pqrs.org/macosx/keyremap4macbook/" target="_blank">KeyRemap4Macbook</a>, to remap all the &#8220;Fx&#8221; keys to their corresponding multimedia keys. Now, after all these effort, I finally have a good-looking, mac compatible mechanical keyboard! I know it is still not a mac keyboard, but the feeling of creating something new, is just more satisfying than anything!</p>
<p>OK, enough talk. Now let&#8217;s look at the pictures. I also attached the design layout and my KeyRemap4Macbook configuration file at the end.</p>
<p><strong>P.S.:</strong></p>
<ul>
<li>Usually DAS keyboards&#8217; quality is pretty good. But the one I received has a stucked key. And the return/exchange experience is just suboptimal. I should have bought it from Amazon or Newegg instead of from DAS&#8217; website directly. Eventually I chose to live with it instead of go through more hassles to exchange it. After all it&#8217;s the not-often-used F12 key.</li>
<li>For anybody who is interested in, and new to mechanical keyboards, here is the must-read guide:<a href="http://www.overclock.net/t/491752/mechanical-keyboard-guide" target="_blank"> Mechanical Keyboard Guide</a>.</li>
</ul>
<div id="attachment_915" class="wp-caption aligncenter" style="width: 584px"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_whole.jpg"><img class="size-large wp-image-915 " title="Keyboard with new key caps" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_whole-1024x413.jpg" alt="" width="574" height="231" /></a>
<p class="wp-caption-text">Keyboard with new key caps</p>
</div>
<hr />
<div id="attachment_902" class="wp-caption aligncenter" style="width: 518px"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_empty1.jpg"><img class="size-full wp-image-902  " title="Keyboard without key caps" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_empty1.jpg" alt="" width="508" height="227" /></a>
<p class="wp-caption-text">Keyboard without key caps</p>
</div>
<hr />
<div id="attachment_914" class="wp-caption aligncenter" style="width: 584px"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_right.jpg"><img class="size-large wp-image-914  " title="Opt, Cmd, Shift and Return" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_right-1024x768.jpg" alt="" width="574" height="430" /></a>
<p class="wp-caption-text">Opt, Cmd, Shift and Return</p>
</div>
<hr />
<div id="attachment_905" class="wp-caption aligncenter" style="width: 584px"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_f13-f15.jpg"><img class="size-large wp-image-905  " title="Multimedia keys" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_f13-f15-1024x486.jpg" alt="" width="574" height="272" /></a>
<p class="wp-caption-text">Multimedia keys</p>
</div>
<hr />
<div id="attachment_913" class="wp-caption aligncenter" style="width: 593px"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_pig.jpg"><img class="size-large wp-image-913  " title="The &quot;pig king&quot; space bar" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_pig-926x1024.jpg" alt="" width="583" height="645" /></a>
<p class="wp-caption-text">The &quot;pig king&quot; space bar</p>
</div>
<hr />
<div id="attachment_910" class="wp-caption aligncenter" style="width: 584px"><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_layout.jpg"><img class="size-large wp-image-910  " title="Keyboard layout" src="http://www.clingmarks.com/wp-content/uploads/2011/11/keyboard2_layout-1024x300.jpg" alt="" width="574" height="168" /></a>
<p class="wp-caption-text">Keyboard layout</p>
</div>
<hr />
<p><strong>2/11/2012 Update: Since this blog was published, I got so many requests for the my design layout file that I decided to put it here for everybody to download under Creative Commons license. You are free to modify it. But if you want to redistribute it, please mention my site or this post. <span style="color: #ff0000;">NO RESALE OR COMMERCIAL USE!</span></strong></p>
<p><strong><a href="http://www.clingmarks.com/wp-content/uploads/2011/11/Yuchens_Mac_Keyboard_Outlines_final.ai_.zip">Adobe Illustrator File: Yuchen&#8217;s_Mac_Keyboard_Outlines_final.ai</a></strong></p>
<div class="box box_pink warrning_box">
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/StillImage" property="dct:title" rel="dct:type">Custom Mac Keyboard Layout For Mechanical Keyboards</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="http://www.clingmarks.com/custom-mac-mechanical-keyboard-lets-have-some-fun/893" property="cc:attributionName" rel="cc:attributionURL">iindigo, yuchen</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="http://www.clingmarks.com/custom-mac-mechanical-keyboard-lets-have-some-fun/893" rel="dct:source">www.clingmarks.com</a>.
</div>
<p/>
<p style="text-align: left;">Finally, here is my configuration file for KeyRemap4Macbook:</p>
<div class="wp_syntax">
<div class="code">
<pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;root<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Remap Num to Clear<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>private.remap_num_to_clear<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToKey-- KeyCode::PC_KEYPAD_NUMLOCK, KeyCode::KEYPAD_CLEAR<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Remap Application to Fn<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>private.remap_application_to_fn<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToKey-- KeyCode::PC_APPLICATION, KeyCode::FN<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Remap Volume Keys<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Up, Down, Mute<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>remap.volumeKeys<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::PC_PRINTSCREEN, ModifierFlag::FN,
      							ConsumerKeyCode::VOLUME_MUTE<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::PC_SCROLLLOCK, ModifierFlag::FN,
      							ConsumerKeyCode::VOLUME_DOWN<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::PC_PAUSE, ModifierFlag::FN,
      							ConsumerKeyCode::VOLUME_UP<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Remap Brightness Keys<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Darker, Brighter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>remap.brightnesskeys<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::F1, ModifierFlag::FN,
      							ConsumerKeyCode::BRIGHTNESS_DOWN<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::F2, ModifierFlag::FN,
      							ConsumerKeyCode::BRIGHTNESS_UP<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Remap Music Play Keys<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Previous, Play/Pause, Next<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>remap.musickeys<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::F9, ModifierFlag::FN,
      							ConsumerKeyCode::MUSIC_PREV<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::F10, ModifierFlag::FN,
      							ConsumerKeyCode::MUSIC_PLAY<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::F11, ModifierFlag::FN,
      							ConsumerKeyCode::MUSIC_NEXT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Remap Eject Key<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Eject<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/appendix<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>remap.ejectkey<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/identifier<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>--KeyToConsumer-- KeyCode::F12, ModifierFlag::FN,
      							ConsumerKeyCode::EJECT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/autogen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/root<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/custom-mac-mechanical-keyboard-lets-have-some-fun/893/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Three20 Learning Notes &#8211; URL Based Navigation</title>
		<link>http://www.clingmarks.com/three20-learning-notes-url-based-navigation/871</link>
		<comments>http://www.clingmarks.com/three20-learning-notes-url-based-navigation/871#comments</comments>
		<pubDate>Fri, 11 Nov 2011 20:10:16 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone development]]></category>
		<category><![CDATA[three20]]></category>
		<category><![CDATA[ttnavigator]]></category>
		<category><![CDATA[tturlaction]]></category>
		<category><![CDATA[url based navigation]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=871</guid>
		<description><![CDATA[Recently I started a new iPhone project, which is an utility application. Not game anymore. To speed up my development process, I decided to use Three20 library for most of the UI development.
Three20 is an open source iOS library, contributed by <a href="http://joehewitt.com/" target="_blank">Joe Hewitt</a>, the developer of original Facebook iPhone app. It is a big package, with very rich functionalities. Many familiar UI elements you see from the facebook app can be found here: the Laucher View (the startup screen with icons for different functionalities), photo album, &#8230; Some UIKit classes are also enhanced, which makes them easier to use (once you have learned it), and also more powerful.
However, everything comes with a cost. And three20 is not perfect either. The most complained issues are the complexity of this framework, not-well-managed dependencies, and lack of documentation. There are some basic information on its official website &#8212; <a href="http://three20.info" target="_blank">three20.info</a>, but far ...]]></description>
			<content:encoded><![CDATA[<p>Recently I started a new iPhone project, which is an utility application. Not game anymore. To speed up my development process, I decided to use Three20 library for most of the UI development.</p>
<p>Three20 is an open source iOS library, contributed by <a href="http://joehewitt.com/" target="_blank">Joe Hewitt</a>, the developer of original Facebook iPhone app. It is a big package, with very rich functionalities. Many familiar UI elements you see from the facebook app can be found here: the Laucher View (the startup screen with icons for different functionalities), photo album, &#8230; Some UIKit classes are also enhanced, which makes them easier to use (once you have learned it), and also more powerful.</p>
<p>However, everything comes with a cost. And three20 is not perfect either. The most complained issues are the complexity of this framework, not-well-managed dependencies, and lack of documentation. There are some basic information on its official website &#8212; <a href="http://three20.info" target="_blank">three20.info</a>, but far from enough for such an advanced framework. Most people, including myself, learned this framework by try-and-error, google search and <a href="http://forums.three20.info/" target="_blank">the community&#8217;s help</a>. There are also some alternative projects that try to provide similar functionalities while fixing three20&#8242;s shortcomings &#8212; such as <a href="https://github.com/jverkoey/nimbus" target="_blank">nimbus</a>, but so far none of them has provided the same level of functionalities as three20 does.</p>
<p>To make things easier for myself, and for other three20 newcomers, I decided to start this blog series for three20. Each of the post will cover one topic in three20. And as the title says, they are just my learning notes. I&#8217;ll include a lot links to other resources and also try to explain it briefly. So here we go!</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-872" title="notes" src="http://www.clingmarks.com/wp-content/uploads/2011/11/1321036772_edit-notes.png" alt="" width="179" height="179" /></p>
<p>Today the topic is &#8220;URL based navigation&#8221;. Be frankly, I think this is one of the smartest idea in three20. In an iOS app, we need to deal with view transitions all the time. And it&#8217;s tedious. The procedure is always the same: find out which view to transit to, decide what animation effect to be used in this transition, pass any parameter if needed. Three20&#8242;s &#8220;URL based navigation&#8221; makes this a lot easier, and more intuitive. The whole idea is to treat view transitions in iOS apps similar to web view transitions in a browser. In a web browser, you don&#8217;t care how to navigate to he next page &#8212; you just click on links (URLs). That is basically the idea of &#8220;URL based navigation&#8221;.</p>
<p>In three20, to implement &#8220;URL based navigation&#8221;, first you define a mapping table which maps urls to view controllers. And when you need to go to another view, just call</p>
<div class="wp_syntax">
<div class="code">
<pre class="objc" style="font-family:monospace;">TTOpenURL<span style="color: #002200;">&#40;</span>URL<span style="color: #002200;">&#41;</span>;</pre>
</div>
</div>
<p>where the &#8220;URL&#8221; is mapped to the view you are going to. Now you know the basic idea of this topic, following are the resources I found useful:</p>
<ul>
<li><a href="http://three20.info/article/2010-10-06-URL-Based-Navigation" target="_blank">Basics of &#8220;URL based navigation&#8221;</a></li>
<p>&nbsp;</p>
<li><a href="http://three20.pypt.lt/url-based-navigation-and-state-persistence">URL-based navigation and state persistence</a></li>
<p>&nbsp;</p>
<li><a href="http://stackoverflow.com/questions/6641223/differences-between-toviewcontroller-tosharedviewcontroller-and-tomodalviewcontr" target="_blank">Difference between &#8220;toViewController&#8221;, &#8220;toSharedViewController&#8221; and &#8220;toModalViewController&#8221;</a></li>
<p>&nbsp;</p>
<li><a href="http://technote.me/how-to-pass-custom-object-during-url-navigati" target="_blank">Passing multiple parameters in URL based navigation</a></li>
<p>&nbsp;</p>
<li>Mapping a URL to a method call:
<div class="wp_syntax">
<div class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>map from<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;tt://urlToDoSomething&quot;</span> toSharedViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>MyViewController class<span style="color: #002200;">&#93;</span> selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>doSomething<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;</pre>
</div>
</div>
</li>
<li>Specify transition animation:
<div class="wp_syntax">
<div class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TTNavigator navigator<span style="color: #002200;">&#93;</span> openURL<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;tt://login&quot;</span> animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span> transition<span style="color: #002200;">:</span>UIViewAnimationTransitionFlipFromLeft<span style="color: #002200;">&#93;</span>;</pre>
</div>
</div>
</li>
</ul>
<p>&nbsp;</p>
<p>Other Three20 Resources:</p>
<ul>
<li>Joe Hewitt: <a href="http://joehewitt.com/" target="_blank">http://joehewitt.com/</a></li>
<li>Joe Hewitt on three20: <a href="http://joehewitt.com/2009/03/23/the-three20-project" target="_blank">http://joehewitt.com/2009/03/23/the-three20-project</a></li>
<li>Threee20 official website: <a href="http://three20.info/" target="_blank">http://three20.info/</a></li>
<li>Three20 forums: <a href="http://forums.three20.info/" target="_blank">http://forums.three20.info/</a></li>
<li>Three20 on github: <a href="https://github.com/facebook/three20" target="_blank">https://github.com/facebook/three20</a></li>
<li>Nimbus (Three20 alternative): <a href="https://github.com/jverkoey/nimbus" target="_blank">https://github.com/jverkoey/nimbus</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/three20-learning-notes-url-based-navigation/871/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>My Favorite Blogs</title>
		<link>http://www.clingmarks.com/my-favorite-blogs/865</link>
		<comments>http://www.clingmarks.com/my-favorite-blogs/865#comments</comments>
		<pubDate>Fri, 14 Oct 2011 18:20:07 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone development]]></category>
		<category><![CDATA[technical blog]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=865</guid>
		<description><![CDATA[Hi! It&#8217;s time for #iDevBlogADay again! Today I want to have a light post, talking about what technical blogs (specifically for iOS development) I follow, and my opinions on them.

<a href="http://www.raywenderlich.com/" target="_blank">www.raywenderlich.com</a>

Posting Freq: High
Pros: This is by far my favorite iOS tutorial blog site. Ray and his co-bloggers did a wonderful job in all aspects, from explaining simple concepts to showing you how to make a fully functional complex games. Everything is made crystal clear. I specially like their style of &#8220;tutorial series&#8221;: which covers a big topic in several posts. Currently the topic is &#8220;iOS 5 Storyboard&#8221;.
Cons: My only wish for them is to cover more UIKit stuff. After all, not everybody is using cocos2d for his/her project.


<a href="http://blog.mugunthkumar.com" target="_blank">MKBlog</a>

Posting Freq: High
Pros: I discovered his blog when I started learning In App Purchase. And then has been following him. His posts covers many different areas and with a lot of attention ...]]></description>
			<content:encoded><![CDATA[<p>Hi! It&#8217;s time for #iDevBlogADay again! Today I want to have a light post, talking about what technical blogs (specifically for iOS development) I follow, and my opinions on them.</p>
<ol>
<li><strong><a href="http://www.raywenderlich.com/" target="_blank">www.raywenderlich.com</a></strong>
<ul>
<li><strong>Posting Freq:</strong> High</li>
<li><strong>Pros:</strong> This is by far my favorite iOS tutorial blog site. Ray and his co-bloggers did a wonderful job in all aspects, from explaining simple concepts to showing you how to make a fully functional complex games. Everything is made crystal clear. I specially like their style of &#8220;tutorial series&#8221;: which covers a big topic in several posts. Currently the topic is &#8220;iOS 5 Storyboard&#8221;.</li>
<li><strong>Cons:</strong> My only wish for them is to cover more UIKit stuff. After all, not everybody is using cocos2d for his/her project.</li>
</ul>
</li>
<li><strong><a href="http://blog.mugunthkumar.com" target="_blank">MKBlog</a></strong>
<ul>
<li><strong>Posting Freq:</strong> High</li>
<li><strong>Pros: </strong>I discovered his blog when I started learning In App Purchase. And then has been following him. His posts covers many different areas and with a lot of attention to details. Very helpful.</li>
<li><strong>Cons:</strong> Since this blog is also his personal blog, sometime there are some posts not related to iOS programming. While I still enjoy reading them, they are certainly not part of the techy posts.</li>
</ul>
</li>
<li><strong><a href="http://idevblogaday.com" target="_blank">iDevBlogADay</a></strong>
<ul>
<li><strong>Posting Freq:</strong> Very High</li>
<li><strong>Pros:</strong> Well, I think I don&#8217;t need to say much about this, <img src='http://www.clingmarks.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  . We all love it.</li>
<li><strong>Cons:</strong> Not all blogs are in the same quality level. This is understandable since people has different priorities and sometime may not in the mood of writing.</li>
</ul>
</li>
<li><strong><a href="http://cocoawithlove.com/" target="_blank">Cocoa With Love</a></strong>
<ul>
<li><strong>Post Freq:</strong> Low</li>
<li><strong>Pros:</strong> Very, very good tutorials. The depth of their posts is one the best. Some posts provided very unique solutions to interesting problems.</li>
<li><strong>Cons: </strong>I just hope they write more often, otherwise it will be a 5 star!</li>
</ul>
</li>
<li><strong><a href="http://www.cimgf.com/" target="_blank">Cocoa is my girlfriend</a></strong>
<ul>
<li><strong>Post Freq:</strong> Medium</li>
<li><strong>Pros:</strong> Similar to &#8220;Cocoa with love&#8221; (both are about Love, isn&#8217;t it? <img src='http://www.clingmarks.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ), this blog has awesome tutorial with great details. The author is also the author of the book &#8220;<a href="http://www.pragprog.com/titles/mzcd/core-data">Core Data: Apple’s API for Persisting Data under Mac OS X</a>&#8221; and &#8220;<a href="http://www.amazon.com/Core-Animation-Simplified-Techniques-Development/dp/0321617754/ref=sr_1_1?ie=UTF8&amp;qid=1307226039&amp;sr=8-1">Core Animation: Simplified Animation Techniques for Mac and iPhone Development</a>&#8220;.</li>
<li><strong>Cons:</strong> Same, more posts will be great!</li>
</ul>
</li>
<li><strong><a href="http://useyourloaf.com/" target="_blank">Use Your Loaf</a></strong>
<ul>
<li><strong>Post Freq: </strong>Medium</li>
<li><strong>Pros:</strong> Very good posts, with a lot of examples and well written.</li>
</ul>
</li>
<li><strong><a href="http://nachbaur.com/" target="_blank">nachbaur.com</a></strong>
<ul>
<li><strong>Post Freq: </strong>Low</li>
<li><strong>Pros: </strong>They don&#8217;t post often, but when they do, you can find some really good stuff, such as the Core Animation series.</li>
</ul>
</li>
<li>Other iOS programming blogs I read:
<ul>
<li><a href="http://www.cocoanetics.com/" target="_blank">Cocoanetics</a></li>
<li><a href="http://iphonedevelopment.blogspot.com/" target="_blank">iPhone Development</a></li>
<li><a href="http://iphoneincubator.com/blog/" target="_blank">iPhone Development Blog</a></li>
</ul>
</li>
</ol>
<p>So what blogs do you read? Please share that with us in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/my-favorite-blogs/865/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Apple, Please be serious about ITC</title>
		<link>http://www.clingmarks.com/apple-please-be-serious-about-itc/851</link>
		<comments>http://www.clingmarks.com/apple-please-be-serious-about-itc/851#comments</comments>
		<pubDate>Fri, 30 Sep 2011 23:47:02 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[random thoughts]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[dns error]]></category>
		<category><![CDATA[infoblox]]></category>
		<category><![CDATA[itc]]></category>
		<category><![CDATA[itunes connect]]></category>
		<category><![CDATA[itunesconnect]]></category>
		<category><![CDATA[outage]]></category>
		<category><![CDATA[site down]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=851</guid>
		<description><![CDATA[Every morning, the first thing I do is grabbing my iphone, and checking my iphone apps&#8217; sale status of the previous day (I use AppSales, which can found at: <a href="https://github.com/omz/AppSales-Mobile">https://github.com/omz/AppSales-Mobile</a>). Today, it failed. It was not really a surprise to me since I know iTunes Connect, Apple developer&#8217;s portal, is often down, with or without notice.
At 10AM, I checked it again. Still no luck. So I logged into ITC&#8217;s website, and wanted to check the sale status from there. When I clicked on the &#8220;Sales and Trends&#8221;, first I got a SSL certificate alert. I ignored it, and let the browser continue. After a few seconds, I saw a shocking view on my browser:
<a href="http://www.clingmarks.com/wp-content/uploads/2011/09/infoblox.png"></a>
When I saw this, the first thing went through my mind is I was on a wrong website. But I checked the url, and yes, it was &#8220;reportingitc.apple.com&#8221;. Then I remembered the warning about the ...]]></description>
			<content:encoded><![CDATA[<p>Every morning, the first thing I do is grabbing my iphone, and checking my iphone apps&#8217; sale status of the previous day (I use AppSales, which can found at: <a href="https://github.com/omz/AppSales-Mobile">https://github.com/omz/AppSales-Mobile</a>). Today, it failed. It was not really a surprise to me since I know iTunes Connect, Apple developer&#8217;s portal, is often down, with or without notice.</p>
<p>At 10AM, I checked it again. Still no luck. So I logged into ITC&#8217;s website, and wanted to check the sale status from there. When I clicked on the &#8220;Sales and Trends&#8221;, first I got a SSL certificate alert. I ignored it, and let the browser continue. After a few seconds, I saw a shocking view on my browser:</p>
<p><a href="http://www.clingmarks.com/wp-content/uploads/2011/09/infoblox.png"><img class="alignnone size-large wp-image-852" title="ITC &quot;Sales and Trends&quot;" src="http://www.clingmarks.com/wp-content/uploads/2011/09/infoblox-1024x674.png" alt="" width="574" height="378" /></a></p>
<p>When I saw this, the first thing went through my mind is I was on a wrong website. But I checked the url, and yes, it was &#8220;reportingitc.apple.com&#8221;. Then I remembered the warning about the SSL cert. So obviously the DNS of this domain (reportingitc.apple.com) was pointing to somewhere else &#8212; in this case, it was infoblox. Was ITC hacked? it might be. But I doubt it. The hacker has no reason to point the site to infoblox, which is another legitimate company. I think it&#8217;s more like something wrong at Apple internally.</p>
<p>A few hours later, ITC was back to normal. As usual, there was no update about this several-hour outage.</p>
<p>We all know Apple making excellent products, with the reputation of great attentions to details. But ITC shows another side of Apple &#8212; inefficient, reckless,  and maybe even unprofessional. For even small websites, they would put a note when the sites are going down for maintenance. But Apple often doesn&#8217;t. For any website, with such an embarrassing event, it would worth a explanation or apology. But none from Apple. I don&#8217;t even want to mention the quality of the ITC site, which is so last generation &#8212; that could be one of the reasons why they have so many down time.</p>
<p>Apple is a very capable company, both technically and business-wise. They have done many things right. But ITC is certainly not one of them. To me, only one thing can explain this: lack of attention. Yes, App Store is important to Apple. But developers not necessarily are. So a basic website is provided to support developers, with basic functionalities, and basic support. In short, to Apple, ITC is too trivia to care.</p>
<p>I really hope Android market can catch up more so that Apple may have a stronger sense of competition, which might leads to more resource on developer support. Hence better ITC. But at the meantime, I just want to let Apple know, please, please be serious about ITC.</p>
<p>P.S.: As many other pointed out, Apple did send out an email a few days before about this maintenance downtime. However, that outage clearly started earlier and ended later. Also, no matter what kind outage it is, the DNS error like that was simply unacceptable. What&#8217;s more, isn’t “no down time” should be the standard for modern websites? Even with releases. When do we see downtime on Google, Amazon, facebook, … ? Apple just took a lower standard on this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/apple-please-be-serious-about-itc/851/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Generate Particles Along A Path</title>
		<link>http://www.clingmarks.com/generate-particles-along-a-path/822</link>
		<comments>http://www.clingmarks.com/generate-particles-along-a-path/822#comments</comments>
		<pubDate>Sat, 17 Sep 2011 17:33:59 +0000</pubDate>
		<dc:creator>yuchen</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone animation]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[opengl animation]]></category>
		<category><![CDATA[opengl es]]></category>
		<category><![CDATA[particle]]></category>
		<category><![CDATA[particle emitter]]></category>
		<category><![CDATA[particle system]]></category>

		<guid isPermaLink="false">http://www.clingmarks.com/?p=822</guid>
		<description><![CDATA[Particle is a big topic in iOS animation. To create realistic smoke, fire or even rain drops or snow falls, having a good particle emitter is the key. But in this blog, I am going to talk about something more than a basic particle emitter.
In most of the cases, particle emitter generates particles randomly &#8212; random color, random size, random direction &#8212; with the control of some key parameters. But it is not always like that. Sometimes we want the generated particles to follow a certain path, such as water trace, a group of firefly, or sparkles in the wind. That&#8217;s what I am going to talk about this time &#8212; how to generate random particles along a path. Before we start, let&#8217;s take a look at the end result first.

As you can see in the demo, at first the particles ran around the character &#8220;2&#8243;; then in the second ...]]></description>
			<content:encoded><![CDATA[<p>Particle is a big topic in iOS animation. To create realistic smoke, fire or even rain drops or snow falls, having a good particle emitter is the key. But in this blog, I am going to talk about something more than a basic particle emitter.</p>
<p>In most of the cases, particle emitter generates particles randomly &#8212; random color, random size, random direction &#8212; with the control of some key parameters. But it is not always like that. Sometimes we want the generated particles to follow a certain path, such as water trace, a group of firefly, or sparkles in the wind. That&#8217;s what I am going to talk about this time &#8212; how to generate random particles along a path. Before we start, let&#8217;s take a look at the end result first.</p>
<p><iframe width="550" height="403" src="http://www.youtube.com/embed/66qQ21ZVOoc" frameborder="0" allowfullscreen></iframe></p>
<p>As you can see in the demo, at first the particles ran around the character &#8220;2&#8243;; then in the second demo I created a path manually by clicking on all the vertices,  and the particle emitter generated particles along the path I just created.</p>
<p>The details of how to create a particle emitter itself is not the focus of this post. There are plenty of good tutorials online about that. Actually my system is based on 71squared&#8217;s tutorial, which in my opinion is the one of the best tutorials in this category (<a href="http://www.71squared.com/2009/05/iphone-game-programming-tutorial-8-particle-emitter/" target="_blank">link to tutorial</a>). Their &#8220;<a href="http://particledesigner.71squared.com/" target="_blank">Particle Designer</a>&#8221; is also a great tool to simplify the process to create beautiful particles. If you haven&#8217;t read their tutorial but want to learn more about particle system, I strongly suggest you to go through it first. This blog is an improvement on top of the particle system implemented by 71squared.</p>
<p>Now let&#8217;s get to the details.</p>
<p>Every a fraction of a second, the particle system will update the positions of all live particles, and generate new particles at its predefined source location (with variances). New particles are generated one by one sequentially. To make them appear along a path (<strong>assuming CGPath in this post</strong>), we need to figure out at a certain timestamp, which point on the path should be the source location.</p>
<p>In the most straightforward case &#8212; when the path is a straight line, it is simple: we know the current moment and total duration, hence we know how many percent of time has passed; using this percentage, we can locate a point between the start point and the end point, which will be the source location to generate the particle for this moment.</p>
<p>It&#8217;s the same for other types of paths. The only difficult part is, since most the paths are polygonal lines, how to locate the point based on the percentage of elapsed time?</p>
<p>Imagine the polygonal line is a rope, and mark all the vertex points as red; now straighten the rope, you have a straight line with many red dots on it. Each dot has its own percentage value based on its distance to the start point and the total length of the rope. Once we are given a percentage value (P), by comparing with each of the vertex, we can eventually find two adjacent vertices with a smaller percentage value (P1), and a greater value (P2). Then we can get the location of the point at this moment:</p>
<pre>
x =  P / (P2 - P1) * (X2 - X1) + X1
y = P / (P2 - P1) * (Y2 - Y1) + Y1
</pre>
<p>So the steps to generate particles along a path are:</p>
<ol>
<li>Once given a path, find all it&#8217;s vertices;</li>
<li>Get the percentage value for each vertex;</li>
<li>Locate the point based on the current percentage value and vertices;</li>
<li>Generate particle at this point.</li>
</ol>
<p>Now let&#8217;s get to the programming part.</p>
<p><strong>1. Find vertices of a CGPath</strong></p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">typedef</span> <span style="color: #a61390;">struct</span> <span style="color: #002200;">&#123;</span>
    CGPoint point;
    CGPoint previousPoint;
    <span style="color: #a61390;">float</span> portionFinished;
<span style="color: #002200;">&#125;</span> CGPathControlPoint;
&nbsp;
CGPathControlPoint <span style="color: #002200;">*</span>controlPoints;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> setAnimationPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGPathRef<span style="color: #002200;">&#41;</span>path <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>animationPath<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        CGPathRelease<span style="color: #002200;">&#40;</span>animationPath<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>controlPoints<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">free</span><span style="color: #002200;">&#40;</span>controlPoints<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    animationPath <span style="color: #002200;">=</span> CGPathRetain<span style="color: #002200;">&#40;</span>path<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #400080;">NSMutableArray</span><span style="color: #002200;">*</span> points <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
	CGPathApply<span style="color: #002200;">&#40;</span>animationPath, points, extractPointsApplier<span style="color: #002200;">&#41;</span>;
&nbsp;
    totalControlPoints <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>points count<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>totalControlPoints &gt; <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        controlPoints <span style="color: #002200;">=</span> <span style="color: #a61390;">calloc</span><span style="color: #002200;">&#40;</span>totalControlPoints, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>CGPathControlPoint<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>controlPoints <span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;not enough memory to save cgpath information&quot;</span><span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">return</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            CGPoint prevPoint <span style="color: #002200;">=</span> CGPointMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span><span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">float</span> totalDistance <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; totalControlPoints; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                CGPoint point <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>points objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span> CGPointValue<span style="color: #002200;">&#93;</span>;
&nbsp;
                <span style="color: #a61390;">float</span> thisDistance <span style="color: #002200;">=</span> 0.0f;
                <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>i <span style="color: #002200;">!=</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    thisDistance <span style="color: #002200;">=</span> sqrtf<span style="color: #002200;">&#40;</span>
                                         <span style="color: #002200;">&#40;</span>point.x <span style="color: #002200;">-</span> prevPoint.x<span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span>point.x <span style="color: #002200;">-</span> prevPoint.x<span style="color: #002200;">&#41;</span>
                                         <span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span>point.y <span style="color: #002200;">-</span> prevPoint.y<span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span>point.y <span style="color: #002200;">-</span> prevPoint.y<span style="color: #002200;">&#41;</span>
                                         <span style="color: #002200;">&#41;</span>;
                <span style="color: #002200;">&#125;</span>
                totalDistance <span style="color: #002200;">+=</span> thisDistance;
&nbsp;
                controlPoints<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>CGPathControlPoint<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>point, prevPoint, totalDistance<span style="color: #002200;">&#125;</span>;
&nbsp;
                prevPoint <span style="color: #002200;">=</span> point;
            <span style="color: #002200;">&#125;</span>
&nbsp;
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; totalControlPoints; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                CGPathControlPoint p <span style="color: #002200;">=</span> controlPoints<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span>;
&nbsp;
                <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>i <span style="color: #002200;">==</span> <span style="color: #2400d9;">0</span> <span style="color: #002200;">&amp;&amp;</span> totalControlPoints &gt; <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    CGPathControlPoint nextP <span style="color: #002200;">=</span> controlPoints<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
                    CGPoint prevP <span style="color: #002200;">=</span> CGPointMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">2.0</span> <span style="color: #002200;">*</span> p.point.x <span style="color: #002200;">-</span> nextP.point.x, <span style="color: #2400d9;">2.0</span> <span style="color: #002200;">*</span> p.point.y <span style="color: #002200;">-</span> nextP.point.y<span style="color: #002200;">&#41;</span>;
&nbsp;
                    controlPoints<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>CGPathControlPoint<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>p.point, prevP, p.portionFinished <span style="color: #002200;">/</span> totalDistance<span style="color: #002200;">&#125;</span>;
                <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
                    controlPoints<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>CGPathControlPoint<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>p.point, p.previousPoint, p.portionFinished <span style="color: #002200;">/</span> totalDistance<span style="color: #002200;">&#125;</span>;
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre>
</td>
</tr>
</table>
</div>
<p>At first, I defined a new struct called &#8220;CGPathControlPoint&#8221;, which includes the current CGPoint and its percentage value. The previous point is also kept there for the purpose of calculating the emission angle, which is not a topic in this blog, so you can ignore that field for now.</p>
<p>Then I defined an array of control points &#8220;controlPoints&#8221;. Our goal is find all the vertices in a CGPath, and put them in this array. The magic happens at line #20:</p>
<div class="wp_syntax">
<div class="code">
<pre class="objc" style="font-family:monospace;">CGPathApply<span style="color: #002200;">&#40;</span>animationPath, points, extractPointsApplier<span style="color: #002200;">&#41;</span>;</pre>
</div>
</div>
<p>CGPathApply is an iOS built-in method since version 2.0. What it does is, &#8220;for each element in a graphics path, calls a custom applier function&#8221;. In our case, the custom callback function is &#8220;extractPointsApplier&#8221;. Basically I created an array first (line 19), and the CGPathApply function will extract all vertices from the CGPath, and apply them to the callback function, which puts them back to the array. Here is the code for the callback function:</p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> <span style="color: #a61390;">void</span> extractPointsApplier<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span> info, <span style="color: #a61390;">const</span> CGPathElement<span style="color: #002200;">*</span> element<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMutableArray</span><span style="color: #002200;">*</span> points <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMutableArray</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> info;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>element<span style="color: #002200;">-</span>&gt;points <span style="color: #002200;">&amp;&amp;</span> element<span style="color: #002200;">-</span>&gt;type <span style="color: #002200;">!=</span> kCGPathElementCloseSubpath<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        CGPoint p <span style="color: #002200;">=</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#40;</span>element<span style="color: #002200;">-</span>&gt;points<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#91;</span>points addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSValue</span> valueWithCGPoint<span style="color: #002200;">:</span>p<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre>
</td>
</tr>
</table>
</div>
<p>In above method, each CGPathElement is actually a vertex. It contains the CGPoint itself and a point type, which includes:</p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">enum</span> CGPathElementType <span style="color: #002200;">&#123;</span>
   kCGPathElementMoveToPoint,
   kCGPathElementAddLineToPoint,
   kCGPathElementAddQuadCurveToPoint,
   kCGPathElementAddCurveToPoint,
   kCGPathElementCloseSubpath
<span style="color: #002200;">&#125;</span>;
<span style="color: #a61390;">typedef</span> <span style="color: #a61390;">enum</span> CGPathElementType CGPathElementType;</pre>
</td>
</tr>
</table>
</div>
<p>The callback function put all points in the array except the ones with type &#8220;kCGPathElementCloseSubpath&#8221;, because that usually means a duplicate point from the last vertex, just with different type.</p>
<p><strong>2. Get percentage value for each vertex</strong><br />
After the call to CGPathApply, we have an array with all the vertices on the path. Then it&#8217;s easy to calculate the distances between two vertices and the total distance. On list 1, after line #20, is the implementation to find out the percentage value (portionFinished) for each vertex.</p>
<p><strong>3. Locate the point</strong><br />
At each moment when we generate particles, we know exactly the elapsed time and total duration (or how many particles has generated and the max number of particles). Hence we know the percentage we have finished. Based on that percentage and the vertices we have extracted, it&#8217;s easy to figure out the current location:</p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGPathControlPoint<span style="color: #002200;">&#41;</span> getPointByFinishedPortion<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">float</span><span style="color: #002200;">&#41;</span> portion <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>portion &lt;<span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> controlPoints<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>portion &gt;<span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> controlPoints<span style="color: #002200;">&#91;</span>totalControlPoints <span style="color: #002200;">-</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; totalControlPoints; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            CGPathControlPoint cp <span style="color: #002200;">=</span> controlPoints<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span>;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>portion &lt; cp.portionFinished<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                CGPathControlPoint prevP <span style="color: #002200;">=</span> controlPoints<span style="color: #002200;">&#91;</span>i <span style="color: #002200;">-</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
                <span style="color: #a61390;">float</span> r <span style="color: #002200;">=</span> portion <span style="color: #002200;">-</span> prevP.portionFinished;
&nbsp;
                <span style="color: #a61390;">float</span> total <span style="color: #002200;">=</span> cp.portionFinished <span style="color: #002200;">-</span> prevP.portionFinished;
                r <span style="color: #002200;">=</span> r <span style="color: #002200;">/</span> total;
&nbsp;
                <span style="color: #a61390;">float</span> x <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>cp.point.x <span style="color: #002200;">-</span> prevP.point.x<span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> r <span style="color: #002200;">+</span> prevP.point.x;
                <span style="color: #a61390;">float</span> y <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>cp.point.y <span style="color: #002200;">-</span> prevP.point.y<span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> r <span style="color: #002200;">+</span> prevP.point.y;
&nbsp;
                <span style="color: #a61390;">return</span> <span style="color: #002200;">&#40;</span>CGPathControlPoint<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>CGPointMake<span style="color: #002200;">&#40;</span>x, y<span style="color: #002200;">&#41;</span>, prevP.point, <span style="color: #2400d9;">0.0</span><span style="color: #002200;">&#125;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// should not happen</span>
        <span style="color: #a61390;">return</span> controlPoints<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre>
</td>
</tr>
</table>
</div>
<p>I think the code is pretty self-explained, so I won&#8217;t go though each line of them here.</p>
<p><strong>4. Generate particles</strong><br />
Finally it&#8217;s time to generate particles. Again, I won&#8217;t cover actually how to generate particles here. Please refer 71squared&#8217;s tutorial and sample program for detail. The only different part is, in &#8220;addParticle&#8221; method, I added following lines:</p>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
</pre>
</td>
<td class="code">
<pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>animationType <span style="color: #002200;">==</span> kAnimatePath<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self initParticle<span style="color: #002200;">:</span>particle atCGPathControlPoint<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self getPointByFinishedPortion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">float</span><span style="color: #002200;">&#41;</span>particleCount <span style="color: #002200;">/</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">float</span><span style="color: #002200;">&#41;</span>maxParticles<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre>
</td>
</tr>
</table>
</div>
<p>Basically the percentage value is calculated based on the generated particle count and the max number of particles, and then the current point is retrieved by using the function in step 3. In the method &#8220;initParticle:atCGPathControlPoint:&#8221;, a particle is generated at the control point, instead of the predefined source location. In this way, a particle is generated at each moment at different location. When they are put together, it looks like the particles are running along the path, just like what we have demoed in the video.</p>
<p>Finally I&#8217;ll put my demo project and some useful links here. Hopefully this post is helpful to you.</p>
<p><strong>Links:</strong></p>
<ol>
<li><a href="http://www.clingmarks.com/download/ParticleTest.zip">Xcode Project</a></li>
<li><a href="Demo Video">http://www.youtube.com/watch?v=66qQ21ZVOoc</a></li>
<li><a href="http://www.71squared.com/2009/05/iphone-game-programming-tutorial-8-particle-emitter/">71squared Tutorial For Particle Emitter</a></li>
<li><a href="http://particledesigner.71squared.com/">71squared&#8217;s Particle Designer</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.clingmarks.com/generate-particles-along-a-path/822/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced

Served from: www.clingmarks.com @ 2013-05-20 14:14:43 -->