tag:blogger.com,1999:blog-41670373149879022782023-11-16T06:49:50.346-08:00iPhone Dev CenterApplication Development for the iPhone using Apple's official SDK.Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.comBlogger44125tag:blogger.com,1999:blog-4167037314987902278.post-20400452215263967162017-06-07T00:40:00.002-07:002017-06-07T00:40:28.898-07:00<div dir="ltr" style="text-align: left;" trbidi="on">
<h4 aria-hidden="" class="event-item-title" ng-bind="::event.title" ng-style="::{ color: event.track.color }" style="box-sizing: inherit; color: #3c5b72; font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 18px; letter-spacing: -0.357px; margin: 0px; padding: 0px; text-size-adjust: auto;">
WWDC 2017 Platforms State of the Union - Quick Recap</h4>
<div>
<br /></div>
<h3 style="text-align: left;">
Xcode 9</h3>
<div>
<br /></div>
<div>
<ul style="text-align: left;">
<li>(Major) Source Editor - Re-written in Swift from Scratch</li>
<li>In-built markdown editor</li>
<li>3x faster, 60FPS scrolling, 50x faster line jump</li>
<li>Tokenize editing</li>
<li>Brand new refactoring system </li>
<li>Open Source Refactoring Engine</li>
</ul>
<div>
<br /></div>
</div>
<h3 style="text-align: left;">
Swift 4</h3>
<div>
<ul style="text-align: left;">
<li>String - Now range replaceable, character collection and bi-directional</li>
<li>Codable - Now easily convert swift types to JSON, Plist. </li>
</ul>
<div>
<br /></div>
</div>
<h3 style="text-align: left;">
Core Technologies</h3>
<div>
<ul style="text-align: left;">
<li>Indexer rearchitected</li>
<li>New build system</li>
<li>Source Control - Github Integration, New navigator option and new clone window in github</li>
<li>Main Thread API Checker</li>
</ul>
<div>
<br /></div>
<h3 style="text-align: left;">
Testing and CI</h3>
<ul style="text-align: left;">
<li>Xcode server built-in</li>
<li>First match API</li>
<li>xcodebuild now test multiple destination in-parallel</li>
</ul>
<div>
<br /></div>
</div>
<h3 style="text-align: left;">
Wireless development</h3>
<div>
<br /></div>
<h3 style="text-align: left;">
Drag & Drop</h3>
<div>
<ul style="text-align: left;">
<li>Large navigation title and new search field</li>
<li>Easy to enable using prefersLargeTitle = true</li>
<li>TableView - Now enable self sizing cells</li>
</ul>
</div>
</div>
Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-74552269458378037972014-06-05T01:51:00.000-07:002014-06-06T04:47:52.466-07:00Apple Swift Programming Language - Hello World<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Swift is a new programming language for iOS and OS X apps that builds on
the best of C and Objective-C, without the constraints of C
compatibility.<br />
<br />
In my efforts to learn
the new language, I’ve decided I will be posting regularly as I step
through the learning process, sharing everything I find. This is the
first post of many on the topic, and I hope you decide to follow along!<br />
<br />
Let's start with basic Xcode template..<br />
<br />
<b>1. Create an Empty Application:</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieQHSyKM_4DmT7q1cUdAMQ1xf-IuV_6aApoXhGCQTzqZtOvst_m6vFYHlsPKplWLDanhcu-XOGfcxnGOvQqllMZmeq-xA206y5q-aCIcUTfXxMLwmdk4X5WFEUHeZHa-M1sSmE5Cwr0A/s1600/Screen+Shot+2014-06-05+at+1.15.26+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieQHSyKM_4DmT7q1cUdAMQ1xf-IuV_6aApoXhGCQTzqZtOvst_m6vFYHlsPKplWLDanhcu-XOGfcxnGOvQqllMZmeq-xA206y5q-aCIcUTfXxMLwmdk4X5WFEUHeZHa-M1sSmE5Cwr0A/s1600/Screen+Shot+2014-06-05+at+1.15.26+pm.png" height="376" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDqHf7Z8IKPBGlzDUt5-sC-2Xbz9lfJQJKgMQA6xR_b_0GqwDxWTxjqjMZogsbAFXlaZvGoqHdPHHMhT1Bzzmaoxtmy922z1Wst0hFyXM5_d7EcWRgPNGnVhxyv8OYFwMi_oZoOR7YIw/s1600/Screen+Shot+2014-06-05+at+1.15.51+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDqHf7Z8IKPBGlzDUt5-sC-2Xbz9lfJQJKgMQA6xR_b_0GqwDxWTxjqjMZogsbAFXlaZvGoqHdPHHMhT1Bzzmaoxtmy922z1Wst0hFyXM5_d7EcWRgPNGnVhxyv8OYFwMi_oZoOR7YIw/s1600/Screen+Shot+2014-06-05+at+1.15.51+pm.png" height="376" width="640" /></a></div>
2. Now create a new UIViewController which will act as a rootViewController<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhis413GsDnRCsFGXePkoYxrVcfka9e9bdLh2QB1C_X4foJljkUvlXk_mkvpqEfETo7DHB1Iz7XPqmAp5uW0czIXMYR7I6n-tNoKveTtgn6LN2F-7dDNqOtGxMSvKsuNAwcdWtmYj2TAw/s1600/Screen+Shot+2014-06-05+at+1.17.02+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhis413GsDnRCsFGXePkoYxrVcfka9e9bdLh2QB1C_X4foJljkUvlXk_mkvpqEfETo7DHB1Iz7XPqmAp5uW0czIXMYR7I6n-tNoKveTtgn6LN2F-7dDNqOtGxMSvKsuNAwcdWtmYj2TAw/s1600/Screen+Shot+2014-06-05+at+1.17.02+pm.png" height="376" width="640" /></a></div>
<br />
3. So for instance in Objective-C where you have this:<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfG6tQlyWqoRt6HEKMYad6A855I7HQexSuv3yq4tmOabaMvSO5Efb283Q0VvSaA0lOYWtQyJzfh9J0Es9ZOz29X7Y7xU2N5NhCu0KdITDXaZlZRzBLQTJ_f1u5UK2Wvlr_dVIvLdXGRtKX/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> RootViewController *vc = [[RootViewController alloc] init];
</code></pre>
<br />
You now have this:<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfG6tQlyWqoRt6HEKMYad6A855I7HQexSuv3yq4tmOabaMvSO5Efb283Q0VvSaA0lOYWtQyJzfh9J0Es9ZOz29X7Y7xU2N5NhCu0KdITDXaZlZRzBLQTJ_f1u5UK2Wvlr_dVIvLdXGRtKX/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var vc = RootViewController()
</code></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaGhjuk0ltP6WN9S_OH7DbogU6iuRrWhYb_aReIr7DBKbsxlpFVgXs9xWrkR1tX0QS5JkshXzob0ah-FFfC4ipwWsK-4wiTI6D8vacC9zfKZ4Nbwma3NEpWtOtTcrqCADKjF8CwzHNkg/s1600/Screen+Shot+2014-06-05+at+1.18.55+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaGhjuk0ltP6WN9S_OH7DbogU6iuRrWhYb_aReIr7DBKbsxlpFVgXs9xWrkR1tX0QS5JkshXzob0ah-FFfC4ipwWsK-4wiTI6D8vacC9zfKZ4Nbwma3NEpWtOtTcrqCADKjF8CwzHNkg/s1600/Screen+Shot+2014-06-05+at+1.18.55+pm.png" height="376" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJCbGDCnh92xYRVVa-VsCw_8H9wdXWpR8m0Eo6lW6Zn9srEWf6krV9OkLQ746Uy563k_0NOdqhAMzcVNTYhoBS8mXVJxlTPlnI4daZTanqAs7CpalEJR2H_oIr6JN0eqpKQbAJEwuAag/s1600/jackie-chan.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJCbGDCnh92xYRVVa-VsCw_8H9wdXWpR8m0Eo6lW6Zn9srEWf6krV9OkLQ746Uy563k_0NOdqhAMzcVNTYhoBS8mXVJxlTPlnI4daZTanqAs7CpalEJR2H_oIr6JN0eqpKQbAJEwuAag/s1600/jackie-chan.jpg" height="218" width="320" /></a></div>
<br />
4. You may have to get rid off from designated initializer from <span style="background-color: #f3f3f3;">RootViewController <span style="background-color: white;">class or you have to create instance with:</span></span>
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfG6tQlyWqoRt6HEKMYad6A855I7HQexSuv3yq4tmOabaMvSO5Efb283Q0VvSaA0lOYWtQyJzfh9J0Es9ZOz29X7Y7xU2N5NhCu0KdITDXaZlZRzBLQTJ_f1u5UK2Wvlr_dVIvLdXGRtKX/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var vc = RootViewController(nibName: nil, bundle: nil)
</code></pre>
<br />
<span style="background-color: #f3f3f3;"><span style="background-color: white;"><span style="background-color: #f3f3f3;"><span style="background-color: white;">5. Now create instance of UINavigationController and attach your vc instance to the rootViewController.</span></span></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDE4kAuJQwbFUiDpM8-EAWkApW3eyzyXMKjz5sHAt2ESsnL7oPL9HTnB0hA84NsJS4BN0-7ZZcxwmEuWJYMB0EUIwCZ3r43QTFM6id2OsFXL6TtWV2rCxuPFW_KySu46dGp7UuVZOgMQ/s1600/Screen+Shot+2014-06-05+at+1.47.10+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDE4kAuJQwbFUiDpM8-EAWkApW3eyzyXMKjz5sHAt2ESsnL7oPL9HTnB0hA84NsJS4BN0-7ZZcxwmEuWJYMB0EUIwCZ3r43QTFM6id2OsFXL6TtWV2rCxuPFW_KySu46dGp7UuVZOgMQ/s1600/Screen+Shot+2014-06-05+at+1.47.10+pm.png" height="376" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrjNY9ZArEB6LNgzUKN3FZ28oDoulfEivW-refmVdUljUfHkHSlOFfKhGl3wW-POdAt9O-mMlS0hjttrWqgp8zbKGuJWKNhRW5ZLbfkc9DhQJvLBpi4q_wnZdCEqX6ciNRX6Nq4A4M7w/s1600/Screen+Shot+2014-06-05+at+1.47.13+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrjNY9ZArEB6LNgzUKN3FZ28oDoulfEivW-refmVdUljUfHkHSlOFfKhGl3wW-POdAt9O-mMlS0hjttrWqgp8zbKGuJWKNhRW5ZLbfkc9DhQJvLBpi4q_wnZdCEqX6ciNRX6Nq4A4M7w/s1600/Screen+Shot+2014-06-05+at+1.47.13+pm.png" height="376" width="640" /></a></div>
<br />
<span style="background-color: #f3f3f3;"><span style="background-color: white;"><span style="background-color: #f3f3f3;"><span style="background-color: white;">6. Build and run!</span></span></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2LLolU9Hhwak1SYnIh6DOxG9cmLzUSujjpO-R1vWiNLATCbzwvUtoUF9nus39Zg4hzH5fAforY7McQU-UvTKuTF74-f-s-cfYAPwuZHVV7LO2gs681FbbPDQKU0PmdnyV4GG_GCTSKQ/s1600/Screen+Shot+2014-06-05+at+1.47.33+pm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2LLolU9Hhwak1SYnIh6DOxG9cmLzUSujjpO-R1vWiNLATCbzwvUtoUF9nus39Zg4hzH5fAforY7McQU-UvTKuTF74-f-s-cfYAPwuZHVV7LO2gs681FbbPDQKU0PmdnyV4GG_GCTSKQ/s1600/Screen+Shot+2014-06-05+at+1.47.33+pm.png" height="400" width="281" /></a></div>
<a href="https://github.com/tariq235/Swift-HelloWorld" target="_blank"><b>Source Code</b></a><br />
<br />
<span style="background-color: #f3f3f3;"><span style="background-color: white;"><span style="background-color: #f3f3f3;"><span style="background-color: white;">We will cover Swift basics in next Article</span></span></span></span><br />
<br />
<span style="background-color: #f3f3f3;"><span style="background-color: white;"><span style="background-color: #f3f3f3;"><span style="background-color: white;">Cheers!! </span></span></span></span><br />
<br /></div>
Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com2tag:blogger.com,1999:blog-4167037314987902278.post-85013413354059448752014-04-07T08:43:00.000-07:002014-04-07T08:43:27.255-07:00Move repo from bitbucket to github <div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Simple and pretty neat trick:<br />
<br />
Lets say your project repository in my <code>$HOME/dev/SampleProject</code> directory.<br />
<br />
<div class="wp_syntax">
<div class="code">
<pre class="bash" style="font-family: monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$HOME</span><span style="color: black; font-weight: bold;">/</span>dev<span style="color: black; font-weight: bold;">/</span><code>SampleProject</code>
git remote rename origin bitbucket
git remote add origin https:<span style="color: black; font-weight: bold;">//</span>github.com<span style="color: black; font-weight: bold;">/sample</span><span style="color: black; font-weight: bold;">/</span><code>SampleProject</code>.git
git push origin master</pre>
<pre class="bash" style="font-family: monospace;"> </pre>
<pre class="bash" style="font-family: monospace;"> </pre>
</div>
</div>
Once your push has been successful to Github then you can delete the old remote by using:<br />
<pre class="bash" style="font-family: monospace;">git remote <span style="color: #c20cb9; font-weight: bold;">rm</span> bitbucket</pre>
<br />
It'll only remove your local reference not your origin repository. <br />
<br />
Tags:<br />
You'll notice that your tags are still not visible in github. You may need to run single command on terminal:<br />
<pre class="bash" style="font-family: monospace;">git push origin --tags -f</pre>
<br />
<div class="wp_syntax">
<div class="code">
<pre class="bash" style="font-family: monospace;">
</pre>
<pre class="bash" style="font-family: monospace;"> </pre>
<pre class="bash" style="font-family: monospace;">
</pre>
</div>
</div>
</div>
Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-5343850629036597972011-03-04T03:15:00.000-08:002011-03-04T03:15:21.695-08:00How To Download a File Only If It Has Been Updated<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">ou should always avoid downloading data over a wireless network whenever possible. If there is a file on a server that your app needs and it’s infrequently updated, then a good approach would be to cache that file in your app and only download it when an update is detected. (You could also package a version of the file inside the app bundle to provide a quick startup time the first time the app is launched.) <br />
There are several ways to solve this problem. The code below does a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">HTTP HEAD request</a>, checks the returned "Last-Modified" header, and compares it with updated timestamp of the local file. (A slightly more efficient approach would be to send a "If-Modified-Since" header with your request. But there seems to be <a href="http://openradar.appspot.com/7869558">some</a> <a href="http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10371.html">issues</a> with that, so proceed carefully with that approach.)<br />
<h3>High-level steps:</h3><ol><li>Create a HTTP HEAD request.</li>
<li>Read the "Last-Modified" header and convert the string to a NSDate.</li>
<li>Read the last modification timestamp of the local file.</li>
<li>Compare the two timstamps.</li>
<li>Download the file from the server if it has been updated.</li>
<li>Save the downloaded file.</li>
<li>Set the last modification timestamp of the file to match the "Last-Modified" header on the server.</li>
</ol>Please note that the code uses synchronous requests to make the code shorter and better illustrate the point. Obviously you should not call this method from the main thread. Depending on your requirements, you could rewrite the code to use asynchronous requests instead.<br />
<br />
- (void)downloadFileIfUpdated {<br />
NSString *urlString = ... your URL ...<br />
DLog(@"Downloading HTTP header from: %@", urlString);<br />
NSURL *url = [NSURL URLWithString:urlString];<br />
<br />
NSString *cachedPath = ... path to your cached file ...<br />
NSFileManager *fileManager = [NSFileManager defaultManager];<br />
<br />
BOOL downloadFromServer = NO;<br />
NSString *lastModifiedString = nil;<br />
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];<br />
[request setHTTPMethod:@"HEAD"];<br />
NSHTTPURLResponse *response;<br />
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error: nil];<br />
if ([response respondsToSelector:@selector(allHeaderFields)]) {<br />
lastModifiedString = [[response allHeaderFields] objectForKey:@"Last-Modified"];<br />
}<br />
<br />
NSDate *lastModifiedServer = nil;<br />
@try {<br />
NSDateFormatter *df = [[NSDateFormatter alloc] init];<br />
df.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";<br />
df.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease];<br />
df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];<br />
lastModifiedServer = [df dateFromString:lastModifiedString];<br />
}<br />
@catch (NSException * e) {<br />
NSLog(@"Error parsing last modified date: %@ - %@", lastModifiedString, [e description]);<br />
}<br />
DLog(@"lastModifiedServer: %@", lastModifiedServer);<br />
<br />
NSDate *lastModifiedLocal = nil;<br />
if ([fileManager fileExistsAtPath:cachedPath]) {<br />
NSError *error = nil;<br />
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:cachedPath error:&error];<br />
if (error) {<br />
NSLog(@"Error reading file attributes for: %@ - %@", cachedPath, [error localizedDescription]);<br />
}<br />
lastModifiedLocal = [fileAttributes fileModificationDate];<br />
DLog(@"lastModifiedLocal : %@", lastModifiedLocal);<br />
}<br />
<br />
// Download file from server if we don't have a local file<br />
if (!lastModifiedLocal) {<br />
downloadFromServer = YES;<br />
}<br />
// Download file from server if the server modified timestamp is later than the local modified timestamp<br />
if ([lastModifiedLocal laterDate:lastModifiedServer] == lastModifiedServer) {<br />
downloadFromServer = YES;<br />
}<br />
<br />
if (downloadFromServer) {<br />
DLog(@"Downloading new file from server");<br />
NSData *data = [NSData dataWithContentsOfURL:url];<br />
if (data) {<br />
// Save the data<br />
if ([data writeToFile:cachedPath atomically:YES]) {<br />
DLog(@"Downloaded file saved to: %@", cachedPath);<br />
}<br />
<br />
// Set the file modification date to the timestamp from the server<br />
if (lastModifiedServer) {<br />
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:lastModifiedServer forKey:NSFileModificationDate];<br />
NSError *error = nil;<br />
if ([fileManager setAttributes:fileAttributes ofItemAtPath:cachedPath error:&error]) {<br />
DLog(@"File modification date updated");<br />
}<br />
if (error) {<br />
NSLog(@"Error setting file attributes for: %@ - %@", cachedPath, [error localizedDescription]);<br />
}<br />
}<br />
}<br />
}<br />
}<br />
<br />
14. It’s always good practice to check if the returned object responds to a selector before you send a message to it.<br />
<br />
22. The "Last-Modified" timestamp on the server includes the name of the month as text. Set the locale of the date formatter to English (assuming that your server responds in English) otherwise the code will fail when run on devices in non-English countries.<br />
<br />
Keep in mind that wireless networks have very high latency. That means it’s very expensive to create a network connection to a server. If the size of the file you want to download is very small, then you will not gain much with the approach above since it will take almost as long time to get the header information as downloading the entire file.<br />
</div><br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com3tag:blogger.com,1999:blog-4167037314987902278.post-2908222531416759042011-03-04T01:33:00.000-08:002011-03-04T01:33:59.973-08:00List of features for Apple iOS 4.3<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on"><div class="post-meta"> <span class="small"><br />
</span><span class="post-category"><a href="http://mobileorchard.com/category/uncategorized/" rel="category tag" title="View all posts in Uncategorized"></a></span> </div><img alt="" class="alignleft size-thumbnail wp-image-6714" height="150" src="http://mobileorchard.com/wp-content/uploads/2011/03/update20110302-150x150.png" title="update20110302" width="150" /><br />
<br />
Along with the the <a href="http://www.google.com/url?sa=t&source=web&cd=7&ved=0CFYQFjAG&url=http%3A%2F%2Fnews.yahoo.com%2Fs%2Fyblog_technews%2F20110302%2Ftc_yblog_technews%2Fapple-unveils-thinner-lighter-more-powerful-ipad-2&ei=0QNvTbPnI8Hjtge3uqDrDg&usg=AFQjCNGkOYiu9HLc6bHz09YjkYoZNerqOg&sig2=vVwn6EswX58LVQVWTEx5GQ" target="_blank">iPad 2</a>, Apple is also going to release iOS 4.3 on March 11. Here are some of the features you can expect:<br />
<br />
<strong>A Configurable Slide Switch for IPad</strong><br />
With iOS 4.3 you will be able to decide whether the hardware switch above the volume buttons on the iPad will control mute or rotation lock in Settings.<br />
<br />
<strong>Safari Performance Boost</strong><br />
Thanks to the Nitro JavaScript engine, an advanced bytecode JavaScript engine, will make web browsing even faster.<br />
<br />
<strong>iTunes Home Sharing</strong><br />
Lose the wires and stream all your content directly over WiFI.<br />
<br />
<strong>Improved Airplay Support</strong><br />
There are several enhancements coming to Airplay, one of the most sought after is the ability to allow apps and even websites to play video using AirPlay Video.<br />
<br />
<strong>Personal Hotspot</strong><br />
Now Verizon iPhone owners won’t be the only ones enjoying the use of a personal hotspot on their iPhone.<br />
Really nothing groundbreaking or ultra-exciting in 4.3 but there are several nice enhancements, which is the norm for a .1. Time to move on to speculating the whens and whats of iOS5.</div><br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-21320132164484606742011-03-04T01:10:00.000-08:002011-03-04T01:10:48.943-08:00iOS Advanced Programming: Event Kit Framework<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">In today’s tutorial we are going to cover the Event Kit Framework and how to add an event to the calendar.<br />
The Event Kit Framework is the way Apple wants us to display or create a calendar entry. With this they are not trying to replace the calendar app, they are trying to give us a way to create an appointment from our app and add it to the calendar app.<br />
To explain this I am going to create a calendar event programmatically. The only problem is that we are not going to be able to test it in the simulator because it doesn’t have a calendar app. To test it you will have to pay $99 to Apple.<br />
Open up Xcode and create a View-Based Application for iPhone. I’m going to call mine “EventApp”.<br />
<h2>Adding the framework</h2>The Event framework is not added by default. You have to right click over the “Frameworks” folder in “Groups and Files” and select Add->Existing Frameworks then find EventKit.framework and click the “Add” button.<br />
<br />
<a href="http://mobileorchard.com/ios-advanced-programming-event-kit-framework/iphone-advance-programming-event-kit-framework-image-1/" rel="attachment wp-att-5382"><img alt="iPhone Advance Programming | Event kit Framework | image 1" class="aligncenter size-full wp-image-5382" height="300" src="http://mobileorchard.com/wp-content/uploads/2010/11/iPhone-Advance-Programming-Event-kit-Framework-image-1.png" width="190" /></a><br />
<h2> </h2><h2>Writing the Code</h2>Now in the EventAppViewController.m import EventKit.<br />
<pre>#import</pre><pre> </pre>Now create a method that will be called when the user touches the “Create event” button that we are going to add later to our interface.<br />
<br />
<pre>-(IBAction) newEvent {
}</pre><pre> </pre>Remember that it must also be added to the .h file as well.<br />
First add the object that is going to give us access to the events database, an EKEventStore.<br />
<br />
<pre>EKEventStore *eventDB = [[EKEventStore alloc] init];</pre><pre> </pre>Then we create a new event object:<br />
<br />
<pre>EKEvent *myEvent = [EKEvent eventWithEventStore:eventDB];</pre><pre> </pre>Now we set some basic properties:<br />
<br />
<pre>myEvent.title = @"New Event";
myEvent.startDate = [[NSDate alloc] init];
myEvent.endDate = [[NSDate alloc] init];
myEvent.allDay = YES;</pre><pre> </pre>I’m setting the start date and end date the same because it is not going to last more than one day and later I it will be an all-day event.<br />
Next we must specify a calendar for that event. I am going to set it to the default calendar.<br />
<br />
<pre>[myEvent setCalendar:[eventDB defaultCalendarForNewEvents]];</pre><pre> </pre>Before we save the event we need to check for errors:<br />
<br />
<pre>NSError *err;</pre><pre>[eventDB saveEvent:myEvent span:EKSpanThisEvent error:&err];</pre><pre> </pre>Now we test to see if there are any errors. If there are no errors we tell the user that the event was successfully created.<br />
<br />
<pre>if (err == noErr) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Event Created"
message:@"Yay!"
delegate:nil
cancelButtonTitle:@"Okay"
otherButtonTitles:nil];
[alert show];
[alert release];
}</pre><pre> </pre>Apple strongly recommends that you notify the user that the event was created. If you create events in the background and you don’t tell the user, Apple will probably reject your app from the App Store, so it is always a good idea to do this.<br />
And last we release the objects:<br />
<br />
<pre>[startDate release];
[endDate release];
[eventStore release];</pre><pre> </pre>The final look of the method should be this:<br />
<br />
<pre>-(IBAction) newEvent {
EKEventStore *eventDB = [[EKEventStore alloc] init];
EKEvent *myEvent = [EKEvent eventWithEventStore:eventDB];
myEvent.title = @"New Event";
myEvent.startDate = [[NSDate alloc] init];
myEvent.endDate = [[NSDate alloc] init];
myEvent.allDay = YES;
[myEvent setCalendar:[eventDB defaultCalendarForNewEvents]];
NSError *err;
[eventDB saveEvent:myEvent span:EKSpanThisEvent error:&err];
if (err == noErr) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Event Created"
message:@"Yay!?"
delegate:nil
cancelButtonTitle:@"Okay"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}</pre><pre> </pre>Now let’s go to interface builder to create the GUI for our App.<br />
<h2>Building the Interface</h2>Open EventAppViewController.xib in the Resources folder.<br />
Add a Round Rect Button and put some text in it.<br />
<br />
<a href="http://mobileorchard.com/ios-advanced-programming-event-kit-framework/iphone-advance-programming-event-kit-framework-image-2/" rel="attachment wp-att-5381"><img alt="iPhone Advance Programming | Event kit Framework | image 2" class="aligncenter size-full wp-image-5381" height="300" src="http://mobileorchard.com/wp-content/uploads/2010/11/iPhone-Advance-Programming-Event-kit-Framework-image-2.png" width="191" /></a><br />
<br />
Then connect it to the newEvent method.<br />
Save and quit Interface Builder and we are done.<br />
<h2>Conclusion</h2>That was easy, wasn’t it?<br />
Apple also included a UI kit for creating events that looks exactly like the calendar app, but it is so easy that i don’t need to explain it, i’m going to leave it to you as homework.</div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-46726376346365025322011-03-03T23:14:00.000-08:002011-03-03T23:14:46.033-08:00Code Sign Errors: profile doesn’t match any valid certificate/private key pair in the default keychain<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">In order to audit and test the app on device before app submission you would have to build the app with valid matching certificate and provisioning profile.<br />
Possible causes to trigger a Code Sign error<br />
<ul><li>switch from individual developer account to corporate developer account on the same mac</li>
<li>upgrade iPhone SDK version</li>
<li>upgrade device iPhone OS version</li>
<li>switch to another mac</li>
<li>lost public/private key</li>
<li>certificate expired</li>
<li>certificate invalid</li>
</ul>Possible Code Sign Errors:<br />
<ul><li>developer certificate can’t be found</li>
<li>provisioning profile can’t be found</li>
<li>profile doesn’t match any valid certificate/private key pair in the default key chain</li>
</ul>Code sign errors will cause device errors showing orange light<br />
I am sharing the process of removing the Code Sign errors and/or device error orange light. Keep in mind you would have to follow the Program Portal instruction for detail steps. Don’t skip any steps or mix any step orders.<br />
Provisioning profile would throw you errors if you didn’t use the valid certificate to generate the public/private key and provisioning profiles.<br />
What can be kept the same<br />
<ul><li>App IDs</li>
<li>Devices</li>
<li>Provisioning</li>
</ul>First of all you must delete the following to avoid unnecessary troubleshooting and matching conflicts on your mac in keychain, harddrive, Xcode organizer, and on your device.<br />
<ul><li>keychain > developer certificate</li>
<li>keychain > private/public key</li>
<li> device > settings > general > profile > provisioning profile</li>
<li>xcode > organizer > devices > provisioning > provisioning profile</li>
<li>iphone configuration utility > provisioning profiles > provisioning profile</li>
</ul>Note: iphone Configuration Utility is a FREE tool you can download. If you don’t have it you can manually delete the provisioning profile.<br />
Revoke your certificate even it is not expired. Revoke your existing certificate and re-create your certificate again. Every step must be executed in the right order. If you forget a single step you would get the same Code Sign error.<br />
<br />
<span style="color: green;"><strong>Step 1) Generate a Certificate Signing Request (CSR)</strong></span><br />
Applications > Utilities > Keychain Access<br />
In the Preferences menu, set Online Certificate Status Protocol (OSCP) and Certificate Revocation List (CRL) to “Off”.<br />
Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority<br />
Name and email address entered matches the information that was submitted when you registered as an iPhone Developer.<br />
Select the ‘Saved to Disk’ radio button and if prompted, select ‘Let me specify key pair information’ and click ‘Continue’. No CA (Certificate Authority) Email Address is required.<br />
If ‘Let me specify key pair’ was selected, specify a file name and click ‘Save’. In the following screen select ‘2048 bits’ for the Key Size and ‘RSA’ for the Algorithm. Click ‘Continue’.<br />
<br />
<span style="color: red;"><strong>CertificateSigningRequest.certSigningRequest</strong></span> CSR file on your desktop is created on desktop.<br />
<br />
<strong><span style="color: green;">Step 2) Submitting a Certificate Signing Request for Approval</span></strong><br />
Revoke Certificate.<br />
Certificates > Development<br />
Request a certificate. Click the ‘Choose file’ button, select your CSR and click ‘Submit’. Request your page until you see the update status. Click the ‘Approve’ button.<br />
<br />
<span style="color: green;"><strong>Step 3) Download & Install Developing Certificates</strong></span><br />
Certificates > Distribution<br />
Control-click the WWDR Intermediate Certificate link and select “Saved Linked File to Downloads” on desktop<br />
Double-click the WWDR Intermediate certificate <strong><span style="color: red;">AppleWWDRCA.cer</span></strong> to launch Keychain Access and install<br />
Download their certificates. Double-click the downloaded .cer file <strong><span style="color: red;">developer_identity.cer</span></strong> to launch Keychain Access and install your certificate.<br />
<br />
To verify the success install, you would see <br />
1) Apple Worldwide Developer Relations Certfication Authority Certificate<br />
2) iPhone Developer: Team Leader Certificate<br />
<br />
<span style="color: green;"><strong>Step 4) Update the existing Provisioning</strong></span><br />
No need to remove the provisioning profile. Click the ‘Modify’ button. Check the box on Certificates. Submit to save the Development Provisioning Profile.<br />
<br />
<span style="color: green;"><strong>Step 5) Install a Development Provisioning Profile</strong></span><br />
Download the profile <strong><span style="color: red;">developer_profile.mobileprovision</span></strong><br />
<br />
Drag the downloaded file into the ‘Organizer’ window within Xcode. This will automatically copy the .mobileprovision file to the proper directory. If the directory does not exist you will need to create it. Click on the ‘+’ button in the Provisioning section of the Organizer window to install your .mobileprovision file.<br />
<br />
<span style="color: green;"><strong>Step 6) Build & Install App on device</strong></span><br />
Launch Xcode and open your project. Select ‘Device – iPhone OS’ from the ‘Device | Debug’ drop down menu.<br />
Highlight the project Target and select the ‘Info’ icon from the top menu bar. Navigate to the ‘Build’ pane. Click the ‘Any iPhone OS Device’ pop-up menu below the ‘Code Signing Identity’ field and select the iPhone Development Certificate/Provisioning Profile pair you wish to sign and install your code with.<br />
Your iPhone Development certificate will be in bold with the Provisioning Profile associated with it in grey above. In the example below, ‘iPhone Developer: Team Leader’ is the Development Certificate and ‘My Development Provisioning Profile’ is the .mobileprovision file paired with it.<br />
If the private key for your iPhone Development certificate is missing, or if your iPhone Development certificate is not included in a provisioning profile, you will be unable to select the iPhone Development Certificate/Provisioning Profile pair and you will see the following. Re-installing the private key or downloading a provisioning profile with your iPhone Development certificate included in it will correct this.</div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com2tag:blogger.com,1999:blog-4167037314987902278.post-47359581368818713412011-03-03T23:11:00.000-08:002011-03-03T23:11:11.267-08:00Xcode Program received signal: “EXC_BAD_ACCESS”<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<div dir="ltr" style="text-align: left;" trbidi="on"><span style="color: red;">Program received signal: “EXC_BAD_ACCESS”</span><br />
<br />
This error occurs in device not simulator.<br />
<br />
Possible Errors:<br />
<ul><li>access protected or non-existent memory space as result of a bad pointer</li>
<li>access memory without alloc init</li>
<li>access memory after released object</li>
<li>remove the [object release] only if you don’t use alloc/copy/retain</li>
<li>trying to access release objects</li>
<li>illegal memory access</li>
</ul><strong>DebuggingAutorelease</strong><br />
<br />
<a href="http://www.cocoadev.com/index.pl?DebuggingAutorelease">http://www.cocoadev.com/index.pl?DebuggingAutorelease</a><br />
This show you how to use Cocoa’s NSZombie debugging class and the command line “malloc_history” tool to find exactly what released object has been accessed in you code.<br />
Running Instruments and checking for leaks will not help troubleshoot EXEC_BAD_ACCESS.<br />
<br />
<strong>Debugging Techniques</strong><br />
<a href="http://www.cocoadev.com/index.pl?DebuggingTechniques" rel="nofollow">http://www.cocoadev.com/index.pl?DebuggingTechniques</a><br />
<br />
NSAssert() call to validate method parameters is to track and avoid passing nils set a breakpoint on objc_exception_throw.</div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-44793177279185739452011-03-03T22:30:00.000-08:002011-03-03T22:30:25.787-08:00iPhone Server Communication<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on"><div class="entry-content"> <div id="page-content"> <h3 id="toc0"><span>We can communicate in many ways with server. One way is using JSON, this is explained as below:</span></h3><h3 id="toc0"><span> </span></h3><strong>1. Starting Communication</strong><br />
<br />
<div> <pre style="text-align: left;"><code>[[[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:
[NSURL URLWithString:urlStr]] delegate:self startImmediately:YES] autorelease];</code>
//urlStr is NSString ref</pre><pre style="text-align: left;"> </pre></div><strong>2. Start receiving data</strong><br />
<div> <pre><code>- (void)connection:(NSURLConnection *)connection didReceiveResponse:
(NSURLResponse *)response{
[receivedData setLength:0];
}</code>
//receivedData is NSMutableData ref</pre><pre> </pre></div><strong>3. Get data in chunks<br />
</strong><br />
<div> <pre><code>- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[receivedData appendData:data];
}</code></pre><pre><code>
</code></pre></div><strong>4. After getting complete data</strong><br />
<div> <pre><code>- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
// json data retrival complete (received data is NSMutableData)
if(receivedData == nil || [receivedData length] == 0){
//handle error in getting response, may be no network
[self showAlertViewWithTitle:@"No network" andMessage:@"Could not open the
page, because internet connection was not found." andTag:0];
return;
}
NSString *responseBody = [[[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding] autorelease];
////NSLog(responseBody);
NSError *jsonParsingError = [[[NSError alloc] init] autorelease];
NSDictionary * jsonData = [NSDictionary dictionaryWithJSONData:
[responseBody dataUsingEncoding:NSUTF8StringEncoding]
error:&jsonParsingError];
NSDictionary *serverError = [jsonData objectForKey:@"error"]==[NSNull null]?
nil:[jsonData objectForKey:@"error"];
if(serverError==nil || [serverError count]==0){
// no error found else
NSDictionary *response = [jsonData objectForKey:@"response"]==[NSNull null]?
nil:[jsonData objectForKey:@"response"];
NSArray *array = [response objectForKey:@"array"]==[NSNull null]?nil:
[response objectForKey:@"array"];</code>
// I have left the code incomplete, its just for understanding</pre><pre> </pre></div><strong>5. Check for null values</strong><br />
Never forget to check null values from JSON data as follows:<br />
<div> <pre><code>NSString *dataValue = [[[array objectAtIndex:i] objectForKey:@"key"]==[NSNull null]?
@"0":[[array objectAtIndex:i] objectForKey:@"key"] intValue];
</code> </pre><pre>Please let me know if you require further explanation..</pre></div></div></div></div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-71254232102575731892011-03-03T22:26:00.000-08:002011-03-03T22:26:20.944-08:00Changing UIView’s Coordinate System<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on"><div class="entry-content"> Some times in our app we want to change the coordinate system of UIView, mostly when we change the orientation of iPhone like Landscape Right or left, So that time, coordinate system as well as appearance of UIView should also change, so here is the code to do that…<br />
<br />
application.statusBarHidden=YES;<br />
<br />
[application setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];<br />
<br />
myUIView = [[MyUIView alloc] initWithFrame:CGRectMake(0,0,480,320)]; //as now width and height is changed<br />
<br />
[window addSubview:myUIView];<br />
<br />
CGAffineTransform transform=CGAffineTransformIdentity;<br />
transform=CGAffineTransformRotate(transform, (90.0f*22.0f)/(180.0f*7.0f));<br />
transform=CGAffineTransformTranslate(transform, 80, 80);<br />
[myUIView setTransform:transform];</div><div class="entry-content"><br />
Now all your subview’s of myUIView will also get transformed. and you will get CGPoint’s of new coordinate system on touch events.<br />
</div></div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-6031043654735853002011-03-03T22:23:00.000-08:002011-03-03T22:23:45.012-08:00UIImageView AnimationImages Memory Leak Mistry Solved<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on"> <header class="entry-header"> </header><br />
<div class="entry-meta"> <span class="meta-prep meta-prep-author"><br />
</span><a href="http://iphone.sanniv.com/2009/08/25/1-uiimageview-animationimages-memory-leak-mistry-solved/" rel="bookmark"><span class="author vcard"></span></a><a class="url fn n" href="http://iphone.sanniv.com/author/admin/" title="View all posts by admin"></a> <div class="entry-content"> We all know that to do animation using <span style="font-weight: bold;">UIImageView</span>, we load images in the <span style="font-weight: bold;">NSArray</span> and then set it to <span style="font-weight: bold;">animationImages</span> property of <span style="font-weight: bold;">UIImageView</span> and then call function <span style="font-weight: bold;">startAnimating</span>.<br />
<br />
But when you try to repeat animation by loading again and again with different images using this method, you start experiencing Crash on iPhone device with status 101 at <span style="font-weight: bold;">Xcode</span> debug. Again, we all know why it crashed, just because of no more memory available for our app in the iPhone device.<br />
But where did our memory went. Here is the answer for that. Every time when we set <span style="font-weight: bold;">NSArray</span> to <span style="font-weight: bold;">animationImages</span>, the whole data gets copied to it because <span style="font-weight: bold;">animationImages</span> is copy property of <span style="font-weight: bold;">UIImageView</span>. And if we try to again set same <span style="font-weight: bold;">animationImages</span> with some other <span style="font-weight: bold;">NSArray</span>, we try to <span style="font-weight: bold;">nil</span> it first then <span style="font-weight: bold;">set</span> with new array. But here we are wrong, when we <span style="font-weight: bold;">nil</span> this property, the <span style="font-weight: bold;">real time memory</span> decreases but the <span style="font-weight: bold;">virtual memory</span> doesn’t decrease because garbage collector is not there.<br />
So instead <span style="font-weight: bold;">nil</span> we should call <span style="font-weight: bold;">release</span> method of this property which will force it to get freed from the <span style="font-weight: bold;">virtual memory</span> too. One more thing you should remember, don’t call release method of this property or don’t try to nil this property in dealloc method where your UIImageView’s reference is released, otherwise either you will get Bad Parameter warning or again virtual memory will not get freed.<br />
<br />
<span style="font-style: italic; font-weight: bold;">Sample code:</span><br />
UIImageView *imgView;<br />
<br />
NSArray *firstArray, *secondArray;<br />
<br />
firstArray= [NSArray arrayWithObjects:[UIImage imageWithContentOfFile: [[NSBundle mainBundle] pathForResource:@”1″ ofType:@”png”]],<br />
[UIImage imageWithContentOfFile: NSBundle mainBundle] pathForResource:@”2″ ofType:@”png”]],<br />
[UIImage imageWithContentOfFile:[[NSBundle mainBundle] pathForResource:@”3″ ofType:@”png”]], nil];<br />
<br />
secondArray=[NSArray arrayWithObjects:[UIImage imageWithContentOfFile:[[NSBundle mainBundle] pathForResource:@”11″ ofType:@”png”]],<br />
[UIImage imageWithContentOfFile:[[NSBundle mainBundle] pathForResource:@”22″ ofType:@”png”]],<br />
[UIImage imageWithContentOfFile:[[NSBundle mainBundle] pathForResource:@”33″ ofType:@”png”]], nil];<br />
<br />
imgView=[[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];<br />
[imgView setAnimationImages:firstArray];<br />
[imgView setAnimationDuration:1];<br />
[imgView setAnimationRepeatCount=0];<br />
[imgView startAnimating];<br />
[self addSubview:imgView];<br />
<br />
After Some time, some where in your code u want to change the animation, then you should do as follows<br />
<br />
[imgView.animationImages release];<br />
[imgView setAnimationImages:secondArray];<br />
[imgView setAnimationDuration:1];<br />
[imgView setAnimationRepeatCount=0];<br />
[imgView startAnimating];<br />
<br />
And At the dealloc method you should do as follows:<br />
<br />
[firstArray release];<br />
firstArray=nil;<br />
<br />
[secondArray release];<br />
secondArray=nil;<br />
<br />
[imgView removeFromSuperView];//If you not already removed this from super view.<br />
[imgView release];<br />
imgView=nil;</div><div class="entry-content"><br />
So, if you try this you will definitely gain your virtual memory and you app will never crash due to low memory. Any suggestions are always appreiciated.<br />
<br />
Thanks<br />
</div></div></div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com1tag:blogger.com,1999:blog-4167037314987902278.post-51979427018935240872011-03-03T22:18:00.000-08:002011-03-03T22:18:42.721-08:00UIImage Tips…<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on"><br />
<span class="meta-prep meta-prep-author"><br />
</span><a href="http://iphone.sanniv.com/2009/08/25/2-uiimage-tips/" rel="bookmark"><span class="author vcard"></span></a><a class="url fn n" href="http://iphone.sanniv.com/author/admin/" title="View all posts by admin"></a> <br />
<div class="entry-content">There are several things which we need to keep in mind when we use <span style="font-weight: bold;">UIImage</span> as follows:<br />
<br />
1.<span style="font-weight: bold;"> UIImage</span> has 4 class methods to create its autorelease instance and 3 instance methods to load image.<br />
<br />
2. When you want to cache the image, so that it can be easily loaded in no time whenever required, you should use:<br />
<br />
<span style="font-weight: bold;">UIImage *tempImage=[UIImage imageNamed:"test.png"];</span> where test.png is the image which will get cached at the first time and will remain in the memory untill app exits. But this should be used only when the image is less in memory size, otherwise your app will have less real and virtual memory for further use. This returns autorelease instance of UIImage that means you do not need to care about its release.<br />
<br />
3. When you want to load the big memory sized images you should use:<br />
<span style="font-weight: bold;">UIImage *tempImage=[UIImage imageWithContentOfFile:[[NSBundle mainBundle] pathForResource:@”test” ofType:@”png”]];</span><br />
<br />
this will not cache the image in the memory for the next time use i.e. when you again load this image this will be loaded from file.<br />
<br />
4. When you don’t want autorelease instance i.e you want to manage its alloc free things on your own you should use:<br />
<span style="font-weight: bold;">UIImage *tempImage=[[UIImage alloc] initWithContentOfFile:[[NSBundle mainBundle] pathForResource:@”test” ofType:@”png”]];</span><br />
<br />
but you have to release it when you are done with it as follows:<br />
<span style="font-weight: bold;">[tempImage release];</span><br />
<br />
5. Whenever you set the UIImage’s instance to UIImageView’s image property, the retain count of UIImage’s instance increases by 1. So never forget to nil the UIImageView’s image property when you are done with it otherwise the UIImage will remain in the virtual memory and will leak.<br />
Example:<br />
<br />
<span style="font-weight: bold;">UIImageView *imgView=[[UIImageView alloc] initWithImage:tempImage];</span><br />
//now tempImage’s retain count will get increase by one. So nil the imgView’s image property whenever you are done with tempImage like this:<br />
imgView.image=nil;<br />
<br />
The difference b/w <span style="font-weight: bold;">autorelease</span> and normal instance is that we have to release the normal instance by calling release method to free up the memory</div></div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-54912382053619125132011-03-03T22:13:00.000-08:002011-03-03T22:16:08.305-08:00Objective C class: Simple Image Cache singleton<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">While working on an iPhone application which makes use of remote data and remote image assets, I realised I needed an object that could quickly and easily cache remote images in the app’s local sandboxed “Documents” folder. To be honest, I kind of feel like I reinvented someone’s wheel here, but I got exactly what I wanted – a small class (singleton) that provides full remote image (not limited to images though) caching within the sandboxed environment on an iPhone.<br />
<span id="more-45"></span><br />
The class is implemented as a singleton since I can’t imagine one would want multiple storage caches running around interfering with each other.<br />
<br />
<strong>ImageCache.h</strong><br />
<br />
<pre>//
// ImageCache.h
//
// Created by Tariq Mohammad on 03/03/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <foundation foundation.h="">
@interface ImageCache : NSObject
{
NSString *documentsDirectory;
NSString *cacheFileUrl;
NSMutableDictionary *dictCache;
}
@property (nonatomic, retain) NSDictionary *dictCache;
+ (ImageCache*) instance;
- (BOOL) isRemoteFileCached:(NSString*)url;
- (NSData*) getCachedRemoteFile:(NSString*)url;
- (BOOL) addRemoteFileToCache:(NSString*)url withData:(NSData*)data;
@end</foundation></pre><pre></pre><pre></pre><strong>ImageCache.m</strong><br />
<br />
<pre>//
// ImageCache.m//
// Created by Tariq Mohammad on 03/03/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "ImageCache.h"
#define kDefaultCacheFile @"imagecache.plist"
//////////////////////////////////////////////////////////////////////////////////////////////////
@interface ImageCache (private)
- (NSString*) makeKeyFromUrl:(NSString*)url;
@end//private ImageCache interface
//////////////////////////////////////////////////////////////////////////////////////////////////
static ImageCache *sharedInstance = nil;
//////////////////////////////////////////////////////////////////////////////////////////////////
@implementation ImageCache
@synthesize dictCache;
////////////////////////////////////////////////////////////////////////////////
- (id)init
{
if ( (self = [super init]) )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
// the path to the cache map
cacheFileUrl = [documentsDirectory stringByAppendingPathComponent:kDefaultCacheFile];
[cacheFileUrl retain];
dictCache = [[NSDictionary alloc] initWithContentsOfFile:cacheFileUrl];
if ( dictCache == nil )
{
dictCache = [[NSMutableDictionary alloc] init];
}
}
return self;
}
////////////////////////////////////////////////////////////////////////////////
- (void)dealloc
{
[cacheFileUrl release];
[dictCache release]
[super dealloc];
}
////////////////////////////////////////////////////////////////////////////////
+ (ImageCache*) instance
{
@synchronized(self)
{
if ( sharedInstance == nil )
{
sharedInstance = [[ImageCache alloc] init];
}
}
return sharedInstance;
}
////////////////////////////////////////////////////////////////////////////////
- (BOOL) isRemoteFileCached:(NSString*)url
{
NSString *imageFilename = [dictCache valueForKey:[self makeKeyFromUrl:url]];
return (imageFilename != nil);
}
////////////////////////////////////////////////////////////////////////////////
- (NSData*) getCachedRemoteFile:(NSString*)url
{
NSString *imageFilename = [dictCache valueForKey:[self makeKeyFromUrl:url]];
NSData *data = nil;
if ( imageFilename != nil )
{
data = [NSData dataWithContentsOfFile:imageFilename];
}
return data;
}
////////////////////////////////////////////////////////////////////////////////
- (BOOL) addRemoteFileToCache:(NSString*)url withData:(NSData*)data
{
BOOL result = NO;
NSString *imageFilename = [url lastPathComponent];
if ( imageFilename != nil )
{
// the path to the cached image file
NSString *cachedImageFileUrl = [documentsDirectory stringByAppendingPathComponent:imageFilename];
result = [data writeToFile:cachedImageFileUrl atomically:YES];
if ( result == YES )
{
// add the cached file to the dictionary
[dictCache setValue:cachedImageFileUrl forKey:[self makeKeyFromUrl:url]];
[dictCache writeToFile:cacheFileUrl atomically:YES];
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Private Methods
- (NSString*) makeKeyFromUrl:(NSString*)url
{
NSString *key = [url stringByReplacingOccurrencesOfString:@"/" withString:@"."];
key = [key stringByReplacingOccurrencesOfString:@":" withString:@"."];
return key;
}
@end</pre><br />
<pre></pre><pre>Let me know if you find this useful, or have suggestions on improving it.</pre><pre></pre></div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com4tag:blogger.com,1999:blog-4167037314987902278.post-89271441440080334142011-02-04T02:36:00.000-08:002011-03-03T22:14:37.649-08:00How To Play YouTube Videos Within an Application<div dir="ltr" style="text-align: left;" trbidi="on"><script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">Playing a video (of a supported file format) on the iPhone is very easy using the MPMoviePlayerController class. You just create an instance of the class and initialize it with the URL of the video. The controller plays the video in full screen mode and returns back to your application when it’s done.<br />
However, if the URL of the video is recognized by the iPhone as a YouTube URL then the Apple URL Scheme mechanism kicks in and launches the YouTube app. In this scenario control will not return to your app after the video has played. (The behavior is equivalent of calling [UIApplication openURL:] with the video URL.)<br />
One workaround is to use a UIWebView and load it with the video URL. The drawback with this approach is that the user will see the rather ugly YouTube mobile web site and has to find and tap on the link of the video to play it.<br />
<br />
<img alt="YouTube Mobile" height="480" src="http://iphoneincubator.com/blog/wp-content/uploads/2009/03/youtubemobile.png" width="320" /><br />
<br />
Another, visually more appealing, option is to create a small UIWebView on your screen and load it with the YouTube embed code. The result is a small button like image that shows the YouTube play button above a screen image from the video. When the user taps the image, the iPhone video player opens in full screen mode as usual, and when the video is done control is returned back to this screen.<br />
<br />
<img alt="YouTube Video Embedded in iPhone App" height="480" src="http://iphoneincubator.com/blog/wp-content/uploads/2009/03/youtubeembeddedvideo.png" width="320" /><br />
<br />
Here’s the code:<br />
<br />
<br />
<ol class="dp-cpp" start="1"><li class="alt">- (<span class="keyword">void</span>)embedYouTube:(NSString*)url frame:(CGRect)frame { </li>
<li class=""> NSString* embedHTML = @<span class="string">"\</span> </li>
<li class="alt"><span class="string"> \</span> </li>
<li class=""><span class="string"> <style type=\"text css\="">\</style type=\"text></span> </li>
<li class="alt"><span class="string"> body {\</span> </li>
<li class=""><span class="string"> background-color: transparent;\</span> </li>
<li class="alt"><span class="string"> color: white;\</span> </li>
<li class=""><span class="string"> }\</span> </li>
<li class="alt"><span class="string"> \</span> </li>
<li class=""><span class="string"> <body style=\"margin:0\">\</body style=\"margin:0\"></span> </li>
<li class="alt"><span class="string"> <embed id=\"yt\" src=\"%@\" type=\"application \="" x-shockwave-flash\=""></embed id=\"yt\" src=\"%@\" type=\"application></span> </li>
<li class=""><span class="string"> width=\"%0.0f\" height=\"%0.0f\">\</span> </li>
<li class="alt"><span class="string"> "</span>; </li>
<li class=""> NSString* html = [NSString stringWithFormat:embedHTML, url, frame.size.width, frame.size.height]; </li>
<li class="alt"> <span class="keyword">if</span>(videoView == nil) { </li>
<li class=""> videoView = [[UIWebView alloc] initWithFrame:frame]; </li>
<li class="alt"> [self.view addSubview:videoView]; </li>
<li class=""> } </li>
<li class="alt"> [videoView loadHTMLString:html baseURL:nil]; </li>
<li class="">} </li>
</ol></div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1">
</script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like></div>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com2tag:blogger.com,1999:blog-4167037314987902278.post-67303917342083530552010-12-08T23:56:00.000-08:002010-12-09T01:01:08.042-08:00Playing Video on iOS4 with the MediaPlayer Framework<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
This tutorial is good for iPhone SDK beginners, as each step assumes no prior-knowledge of the Xcode environment. Intermediate developers may wish to jump straight to step 4, and those who just want to see the code snippets for playing a video can jump to steps 6 and 7. <br />
<h4>MediaPlayer Tutorial Overview:</h4><strong>Step 1. Create a New View-Based Project</strong><br />
This step will demonstrate the creation of a new view-based application template. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 1 - Creating a project in Xcode" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step1.jpg" style="display: inline;" /> </div><br />
<strong>Step 2. Convert the Video File to an iOS Compatible Format</strong><br />
This step discusses the video file formats and codecs supported by the iPhone OS, and the steps necessary to convert a video from an unsupported format to a supported format using iTunes. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 2 - Valid Video File Formats" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step2.jpg" style="display: inline;" /> </div><br />
<strong>Step 3. Add Project Resources</strong><br />
This step displays the various project files that will be used in the MoonWalk application and demonstrates the process of adding them into the project resources folder. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 3 - Adding Project Resources" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step3.jpg" style="display: inline;" /> </div><br />
<strong>Step 4. Add the MediaPlayer Framework & Configure MoonWalkViewController.h</strong><br />
This step will demonstrate adding the MediaPlayer framework to the project and will customize the Moon Walk header file with the method prototype used in the application. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 4 - Adding the Framework in MoonWalk ViewController" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step4.jpg" style="display: inline;" /> </div><br />
<strong>Step 5. Create the Interface with Interface Builder</strong><br />
This step will utilize Interface Builder to customize the application interface with the graphic files provided. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 5 - Building the Interface with Interface Builder" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step5.jpg" style="display: inline;" /> </div><br />
<strong>Step 6. Add the “play” Method Implementation to MoonWalkViewController</strong><br />
This step demos the use of the MPMoviePlayerController class in order to play the moon walk landing video. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 6 - MPMoviePlayerController" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step6.jpg" style="display: inline;" /> </div><strong>Step 7. Add an NSNotification Callback for MPMoviePlayerPlaybackDidFinishNotification</strong><br />
This step introduces the user to the NSNotificationCenter and resolves the memory leak created in step 6. The NSLog() method created in step 6 is demonstrated and a small bug introduced in that function is fixed. <br />
<div class="tutorial_image"><img alt="iOS Media Player Framework Step 7 - NSNotificationCenter Example" src="http://d339vfjsz5zott.cloudfront.net/18_iOSMediaPlayerIntro/iOS-MediaPlayer-Step1.jpg" style="display: inline;" /> </div><div class="tutorial_image"> </div><div class="tutorial_image"> </div><div class="tutorial_image"><a href="http://redirectingat.com/?id=1342X589347&xs=1&url=http%3A%2F%2Fmobiletuts.s3.amazonaws.com%2F18_iOSMediaPlayerIntro%2FMoonWalk-Mobiletuts.zip&sref=http%3A%2F%2Fmobile.tutsplus.com%2Ftutorials%2Fiphone%2Fiphone-sdk-playing-video-with-the-mediaplayer-framework%2F"><b>Download Source File</b></a> </div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-63866739205209812232010-12-08T05:57:00.000-08:002010-12-09T01:01:17.515-08:00Steve Jobs Gives His Take on Competing Mobile Platforms<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div class="post-excerpt">Here’s an interesting post on what Steve Jobs thinks of the other competing mobile platforms out there. Though very insightful, I would not 100% agree on many of the viewpoints. They are obviously biased in favour of Apple <img alt=":)" class="wp-smiley" src="http://www.edumobile.org/iphone/wp-includes/images/smilies/icon_smile.gif" /> He spoke about Blackberry, Android, The Tablet Market, Nokia, Smartphones, etc etc. Here’s his full take…<br />
</div><div class="post-content">Here’s an interesting post on what Steve Jobs thinks of the other competing mobile platforms out there. Though very insightful, I would not 100% agree on many of the viewpoints. They are obviously biased in favour of Apple <img alt=":)" class="wp-smiley" src="http://www.edumobile.org/iphone/wp-includes/images/smilies/icon_smile.gif" /> <br />
He spoke about Blackberry, Android, The Tablet Market, Nokia, Smartphones, etc etc. Here’s his full take…<br />
<br />
<strong>On BlackBerry</strong><br />
<br />
“We’ve now passed RIM. And I don’t see them catching up with us in the foreseeable future. They must move beyond their area of strength and comfort, into the unfamiliar territory of trying to become a software platform company.”<br />
“I think it’s going to be a challenge for them to create a competitive platform and to convince developers to create apps for yet a third software platform after iOS and Android.”<br />
<br />
<strong>On Android</strong><br />
<br />
“Last week, Eric Schmidt reiterated that they are activating 200,000 Android devices per day, and have around 90,000 apps in their app store. For comparison, Apple has activated around 275,000 iOS devices per day on average for the past 30 days, with a peak of almost 300,000 iOS devices per day on a few of those days. And Apple has 300,000 apps on its App Store.”<br />
“Google loves to characterize Android as “open,” and iOS and iPhone as “closed”. We find this a bit disingenuous, and clouding the real difference between our two approaches.”<br />
“Android is very fragmented. Many Android OEMs, including the two largest, HTC and Motorola, install proprietary user interfaces to differentiate themselves from the commodity Android experience. The user’s left to figure it all out. Compare this with iPhone, where every handset works the same.”<br />
“Many Android apps work only on selected Android handsets, running selected Android versions. And this is for handsets that have been shipped less than 12 months ago! Compare this with iPhone, where there are two versions of the software, the current and the most recent predecessor, to test against.”<br />
“In reality, we think the open versus closed argument is just a smokescreen to try and hide the real issue, which is, “What’s best for the customer – fragmented versus integrated?” We think Android is very, very fragmented, and becoming more fragmented by the day.”<br />
<br />
<strong>On the smartphone market</strong><br />
<br />
“I think right now it’s a battle for the mindshare of developers and for the mindshare of customers, and right now iPhone and Android are winning that battle.”<br />
<br />
<strong>On Nokia (and developers)</strong><br />
<br />
“Nokia makes $50 handsets, and we don’t know how to make a great smartphone for $50. We’re not smart enough to have figured that one out yet, but believe me I’ll let you know when we do.”<br />
“Most of them [developers] will not follow you. Most of them will say, ‘I’m sorry, but I’m not going to write down a watered-down version of my app just because you’ve got this phone that you can sell for $50 less, and you’re begging me to write software for it’.”<br />
<br />
<strong>On acquisition possibilities</strong><br />
<br />
“We strongly believe that one or more very strategic opportunities may come along, that we are in a unique position to take advantage of because of our strong cash position.”<br />
“We don’t let it burn a hole in our pocket, we don’t allow it to motivate us to do stupid acquisitions. And so I think that we’d like to continue to keep our powder dry, because we do feel that there are one or more strategic opportunities in the future.”<br />
<br />
<strong>On the tablet market</strong><br />
<br />
“I’d like to comment on the “avalanche” of tablets poised to enter the market in the coming months. First, it appears to be just a handful of credible entrants, not exactly an avalanche. Second, almost all of them use seven-inch screens, as compared to iPad’s near 10-inch screens.”<br />
“The screen measurements are diagonal, so that a seven-inch screen is only 45 percent as large as iPad’s 10-inch screen… While one could increase the resolution of the display to make up some of the difference, it is meaningless unless your tablet also includes sandpaper, so that the user can sand down their fingers to around one-quarter of their present size.”<br />
“Every tablet user is also a smartphone user. No tablet can compete with the mobility of a smartphone… The seven-inch tablets are tweeners: too big to compete with a smartphone, and too small to compete with an iPad.”<br />
“iPad now has over 35,000 apps on the App Store. This new crop of tablets will have near zero.”<br />
</div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-25232225438985406182010-12-08T03:35:00.000-08:002010-12-09T01:01:30.316-08:00Limitations of Data Protection in iOS 4<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<center><img alt="Data Protection at work in iOS 4" class="aligncenter" height="400" src="http://km.support.apple.com/library/APPLE/SECRET_PRODUCTS/S_PROJECT_13/HT4175/HT4175_01--data_protection_enabled-001-en.png" width="278" /></center> <br />
Apple’s recently released iOS 4 provides enhanced “data protection”, but there is very little on the web now that explains what this really means. In this post I clarify what data protection is and what some of its limitations are.<br />
<h2>What Data Protection Is</h2>The release of the iPhone 3GS (and later iPod Touch 3rd Generation) brought hardware-based full disk encryption (FDE) to the iPhone. This was designed to accomplish one thing: instantaneous remote wipe. While the iPhone 3G had to overwrite every bit in flash memory (sometimes taking several hours), disk wiping on the 3GS worked by simply erasing the 256-bit AES key used to encrypt the data.<br />
<br />
Unfortunately, disk encryption on the iPhone did little beyond enabling remote wipe. Mobile forensicator <a href="http://www.zdziarski.com/">Jonathan Zdziarski</a> <a href="http://www.zdziarski.com/blog/?p=516">found</a> that the iPhone OS automatically decrypts data when a request for data is made, effectively making the encryption worthless for protecting data.<br />
So I was curious to learn what encryption improvements were made in iOS 4. Apple calls its new encryption scheme “data protection”, a substantial improvement in security design. Data protection has the primary advantage of using the user’s passcode or password to derive a key that is used to encrypt data on the device. When the phone is locked or turned off, the key is immediately erased, making data secured on the device inaccessible.<br />
<h2>Limitations of Data Protection</h2>The details of how data protection works are described in Apple’s recently released <a href="http://developer.apple.com/videos/wwdc/2010/">videos</a> from its world-wide developers conference (see Session 209 “Securing Application Data”). This information is protected by an NDA, but I’ll summarize at a high level five basic limitations.<br />
<br />
First, to make data encryption work a user must have an iPhone 4, iPhone 3GS, or iPod Touch 3rd Gen (previous iPhones don’t support hardware encryption). Importantly, 3GS users who upgrade to iOS must restore the device as the iOS 3 file system doesn’t support the new data protection scheme. The steps to do this are described <a href="http://support.apple.com/kb/HT4175">here</a>.<br />
<br />
Second, files are encrypted individually by software classes that implement data protection. This means that developers must deliberately choose to use data encryption in their apps, otherwise data is unprotected. Currently, Apple says that so far <a href="http://support.apple.com/kb/HT4175">only Mail</a> is setup to use data encryption, although they say they will eventually bring data encryption to other applications. This means that even with data encryption enabled, text messages, contacts, photos, web history—in short, everything else—is left unprotected.<br />
<br />
Third, a user must use a passcode or password. The strength of the password is up to the user, which is generally a <a href="http://www.nytimes.com/2010/01/21/technology/21password.html">good</a> <a href="http://www.wired.com/politics/security/commentary/securitymatters/2007/01/72458">thing</a> for forensicators.<br />
<br />
Fourth, to mitigate the threat of a brute force attack, the file encryption requires a key generated by the device itself, in addition to the key derived from the user’s password. This slows brute forcing because the encryption key generation process is slow by design: the iPhone 4 takes about 50 milliseconds to derive the key once the user submits a password. This means an attacker can guess only about 20 passwords per second.<br />
<br />
This might not sound like much of a speed reduction, but this actually compares well with software-based encryption products. By comparison, I’ve used AccessData’s Password Recovery Toolkit to guess up to 900,000 passwords a second for encrypted Microsoft Office files. Encrypted PGP files allow about <a href="http://www.wired.com/politics/security/commentary/securitymatters/2007/01/72458">900 password guesses per second</a>.<br />
<br />
Fifth, a weakness in the data protection system is something called the “Escrow Keybag”, which is a collection of keys necessary to decrypt every file on the device without requiring the user’s password. This was done to allow computers to sync with the iPhone without asking the user for the password.<br />
This was a deliberate trade-off to enhance user experience. Apple’s rationale was that if the PC containing the escrow keybag was obtained, an attacker most likely already had the user’s important data anyway. For forensicators, this means that if a user’s computer is obtained along with the iPhone, it will be much easier to decrypt the user’s protected data.<br />
<br />
<b>Updated August 6, 2010</b>: Elcomsoft has <a href="http://www.elcomsoft.com/PR/eppb_100805_en.pdf">announced</a> that its iPhone Password Breaker tool can recover iPhone keychains (probably the escrow keybag) from password-protected iPhone backups.<br />
<h2>Summary</h2>Currently, data protection in iOS 4 is still limited. Apps must be updated to use data protection and currently only Mail does so. All other data can be <a href="http://www.zdziarski.com/blog/?p=516">easily obtained</a> without the users password.<br />
Even so, data protection in iOS 4 represents a significant improvement over encryption in iOS 3. It is clear that Apple is striving to iteratively improve security on the iPhone, which is a good thing.<br />
In the meantime, it looks like forensicators won’t have to worry too much about getting the data they need off of an iPhone.<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-80938389857743806492010-12-08T03:23:00.000-08:002010-12-09T01:02:41.049-08:0010 iPhone Memory Management Tips<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
Memory management in the iPhone is a hot topic. And since tonight I’m talking about it on tonight’s monthly meetup of the French-speaking Swiss iPhone Developers group, I might as well share some tips here from my own experience.<br />
I won’t go dive through the basics; I think that Scott Stevenson did a great job in his <a href="http://cocoadevcentral.com/d/learn_objectivec/">“Learn Objective-C” tutorial at CocoaDevCentral</a>, from where the image below comes. I’m just going to highlight some iPhone-specific issues here and there, and provide some hints on how to solve them.<br />
<a href="http://cocoadevcentral.com/d/learn_objectivec/"><img alt="learnobjectivec-referencecounting.png" border="0" class="alignnone size-medium" height="108" src="http://akosma.com/wp/wp-content/uploads/2009/11/learnobjectivec-referencecounting1.png" width="440" /></a><br />
<span id="more-1324"></span><br />
To begin with, some important background information:<br />
<ul><li>The iPhone 3G has 128 MB of RAM, but at least half of it might be used by the OS; this might leave as little as 40 MB to your application… but remember: you will get memory warnings even if you only use 3 MB;</li>
<li>The iPhone does not use garbage collection, even if it uses Objective-C 2.0 (which can use garbage collection on Leopard, nevertheless);</li>
<li>The basic memory management rule is: for every [ alloc | retain | copy ] you have to have a [ release ] somewhere;</li>
<li>The Objective-C runtime does not allow objects to be instantiated on the stack, but only on the heap; this means that you don’t have “automatic objects”, nor things like auto_ptr objects to help you manage memory;</li>
<li>You can use autorelease objects; but watch out! Since they are not released until their pool is released, they can become <i>de facto</i> memory leaks for you…;</li>
<li>The iPhone does not have a swap file, so forget about virtual memory. When there is no more memory, <b>there is</b> no more memory.</li>
</ul>Having said this, here’s my list of tips:<br />
<ul><li>Respond to Memory Warnings</li>
<li>Avoid Using Autoreleased Objects</li>
<li>Use Lazy Loading and Reuse</li>
<li>Avoid UIImage’s imageNamed:</li>
<li>Build Custom Table Cells and Reuse Them Properly</li>
<li>Override Setters Properly</li>
<li>Beware of Delegation</li>
<li>Use Instruments</li>
<li>Use a Static Analysis Tool</li>
<li>Use NSZombieEnabled</li>
</ul><h3>Respond to Memory Warnings</h3>Whatever you do in your code, please do not forget to respond to memory warnings! I can’t stress this much. I have seen application crashes just because the handler methods were not present on the controllers, which means that, even if you do not have anything to clear in your controller, at least do this:<br />
<br />
- (void)didReceiveMemoryWarning<br />
{<br />
[super didReceiveMemoryWarning];<br />
}<br />
<br />
And you might as well respond to them on your application delegate, as follows:<br />
<br />
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application<br />
{<br />
[[ImageCache sharedImageCache] removeAllImagesInMemory];<br />
}<br />
<br />
<br />
For the description of the ImageCache class, continue reading <img alt=";)" class="wp-smiley" src="http://akosma.com/wp/wp-includes/images/smilies/icon_wink.gif" /> <br />
Or finally, as an NSNotification:<br />
<br />
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];<br />
[center addObserver:self<br />
selector:@selector(whatever:)<br />
name:UIApplicationDidReceiveMemoryWarningNotification<br />
object:nil];<br />
<br />
<br />
<br />
<h3>Avoid Using Autoreleased Objects</h3>Autoreleasing objects is easy and useful, but on the iPhone you should be careful with it. By default there is an NSAutoreleasePool instance created for you at the beginning of the main() function, <del datetime="2009-02-26T15:21:04+00:00">but this pool is not cleared up until your application quits! This means that during runtime, your autoreleased objects are <i>de facto</i> memory leaks, since they are retained until the application quits.</del> <b>(please see the comments below; I have experienced better performance when avoiding autoreleased objects, but my understanding of pools is misleading <img alt=":)" class="wp-smiley" src="http://akosma.com/wp/wp-includes/images/smilies/icon_smile.gif" /> </b><br />
I started getting a better performance from my iPhone apps when I stopped using some methods creating autoreleased objects, for example:<br />
<br />
// Instead of<br />
NSString *string = [NSString stringWithFormat:@"value = %d", intVariable];<br />
<br />
// use<br />
NSString *string = [[NSString alloc] initWithFormat:@"value = %d", intVariable];<br />
...<br />
[string release];<br />
<br />
<br />
<br />
In version 2.0 of the iPhone OS there was also the problem that some “convenience methods” did not work at all; I’m sure you’ve experienced your application crashing when using NSDictionary’s dictionaryWithObjects:forKeys: and then finding out that a replacing that with initWithObjects:forKeys: made your application run just fine. The NDA did not help at the time!<br />
This does not mean that you can’t use autoreleased objects; you should use them, for example, when you have factory methods returning objects not owned neither by the factory nor by the client calling it. You can also use autorelease pools in loops, when you need to allocate lots of small objects, but remember to release the pool right afterwards:<br />
<br />
<br />
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];<br />
for (id item in array)<br />
{<br />
id anotherItem = [item createSomeAutoreleasedObject];<br />
[anotherItem doSomethingWithIt];<br />
}<br />
[pool release];<br />
<br />
<br />
<br />
Remember to always release the pool in the same context where it was created. CocoaDev has an interesting discussion about <a href="http://www.cocoadev.com/index.pl?NSAutoreleasePool">using NSAutoreleasePools in loops</a>.<br />
Oh, and please, never release an autoreleased object on the iPhone: your application will crash almost instantly.<br />
<h3>Use Lazy Loading and Reuse</h3>If your application consists of several different controllers embedded into each other, defer their instantiation until the last possible moment; this means in practical terms that your init method is minimalistic, and that you do more stuff when you need it.<br />
<br />
<h3>Avoid UIImage’s imageNamed:</h3>Alex Curylo has written <a href="http://www.alexcurylo.com/blog/2009/01/13/imagenamed-is-evil/">an absolutely great article</a> about the problems with UIImage’s imageNamed: static method. It seems (and in my tests this appears to be true) that the iPhone OS (versions 2.0 and 2.1 at least) uses an internal cache for images loaded from disk using imageNamed:, and that in cases of low memory this cache is not cleared up completely (this seems to be corrected with version 2.2, though, but I cannot confirm).<br />
<br />
<h3>Build Custom Table Cells and Reuse Them Properly</h3>Remember to always use static NSString identifiers for your cells, which helps the UITableView class to reuse them and reduce memory consumption:<br />
<br />
- (UITableViewCell *)tableView:(UITableView *)tableView<br />
cellForRowAtIndexPath:(NSIndexPath *)indexPath<br />
{<br />
Item *item = [items objectAtIndex:indexPath.row];<br />
static NSString *identifier = @"ItemCell";<br />
<br />
ItemCell *cell = (ItemCell *)[tableView<br />
dequeueReusableCellWithIdentifier:identifier];<br />
<br />
if (cell == nil)<br />
{<br />
cell = [[[ItemCell alloc] initWithIdentifier:identifier]<br />
autorelease];<br />
}<br />
cell.item = item;<br />
return cell;<br />
}<br />
<br />
I also avoid using NIBs when working with table cells, for performance reasons. I prefer to draw the cells through my own subclasses of UITableViewCell, themselves using overridden setters for their properties, which takes me to the next point.<br />
<br />
<h3>Override Setters Properly</h3>As I said above, I tend to create my own subclasses of UITableViewCell, providing a simple property through which I change the model class holding the data that the cell is supposed to show. This has the effect of changing all the values of the fields and labels to the values corresponding to those of the model instance.<br />
<br />
<h3>Beware of Delegation</h3>If your code is delegate of some other object which you are about to release, remember to set its delegate property to nil before releasing it; otherwise, the object might “think” that its delegate is still there, and will send a message to an invalid pointer.<br />
<br />
<h3>Use Instruments</h3>The “Leaks” instrument is your friend, and you should use it after you write the first line of code. Typically, I launch it every time before doing a checkin of some new code. In Xcode, select “Run / Start with Performance Tool / Leaks” and you’re done. You can use it in the simulator or on your device.<br />
<h3>Use a Static Analysis Tool</h3>Use the <a href="http://clang.llvm.org/StaticAnalysis.html">LLVM/Clang Static Analyzer</a> tool. This amazing tool will catch naming errors (regarding the Objective-C naming conventions) and some hidden memory leaks, which are particularly nasty when using CoreFoundation libraries (Address Book, sound, CoreGraphics, etc). You can add it to your daily build script, it’s very easy to use.<br />
But you must use it. Enough said.<br />
<h3>Use NSZombieEnabled</h3>Lou Franco has posted an <a href="http://loufranco.com/blog/files/debugging-memory-iphone.html">excellent article about how to use NSZombieEnabled</a> in your development cycle. The idea is to be able to find which messages are being sent to invalid pointers, referencing objects which have been released somewhere in your code. Always remember who’s the owner of your objects, and check for existence elsewhere!<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-30993660172327835112010-12-08T03:13:00.000-08:002010-12-09T01:02:56.954-08:00Bypassing iPhone 3G[s]/ iPhone 4 Encryption<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<b>Bypassing Passcode and Backup Encryption:</b><br />
<a href="http://www.youtube.com/watch?v=5wS3AMbXRLs">http://www.youtube.com/watch?v=5wS3AMbXRLs</a><br />
<br />
<b>Forensic Recovery of Raw Disk:</b><br />
<a href="http://www.youtube.com/watch?v=kHdNoKIZUCw">http://www.youtube.com/watch?v=kHdNoKIZUCw</a><br />
<br />
<b>What Data Can You Steal From an iPhone in 2 Minutes?</b><br />
<a href="http://www.youtube.com/watch?v=34f47m-lYSg">http://www.youtube.com/watch?v=34f47m-lYSg</a><br />
<br />
These YouTube videos demonsrate just how easy it is to bypass the passcode and backup encryption in an iPhone 3G[s] within only a couple of minutes’ time. A second video shows how easily tools can pull an unencrypted raw disk image from the device. The seriousness of the iPhone 3G[s]‘ vulnerabilities may make enterprises and government agencies think twice before allowing these devices to contain confidential data. Apple has been alerted to and aware of these vulnerabilities for many years, across all three models of iPhone, but has failed to address them.<br />
<br />
The 3G[s] has penetrated the government/military markets as well as top fortune-100s, possibly under the misleading marketing term “hardware encryption”, which many have taken at face value. Serious vulnerabilities such as these threaten to put our country’s national security at risk. Apple’s only fix thus far has been to consistently put a few nails on the front door, but they have thus far failed to fix the major underlying design issues that allow for this threat. Unfortunately, the only way Apple seems to listen is through addressing such problems publicly, as all previous attempts to talk with them have failed. I sincerely hope they fix these issues before a breach occurs.<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com1tag:blogger.com,1999:blog-4167037314987902278.post-69842926601852961642010-11-26T02:02:00.000-08:002010-12-09T01:03:11.211-08:00Easy, Modular Code Sharing Across iPhone Apps: Static Libraries and Cross-Project References<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
Finding an elegant way to reuse and share code (i.e., libraries) across separate iPhone applications can be a bit tricky at first, especially considering Apple’s restrictions on dynamic library linking and custom <a href="http://developer.apple.com/DOCUMENTATION/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html#//apple_ref/doc/uid/20002303" target="_blank">Frameworks</a>. Most people agree that the best solution is to use <a href="http://en.wikipedia.org/wiki/Static_library" target="_blank">static libraries</a>. This tutorial builds on that solution, showing how your Xcode project can <i>reference a second Xcode project</i>–one which is used to build a static library. This allows you to automatically build that static library with the rest of your app, using your current build configuration (e.g., debug, release, etc.) and avoid pre-building several versions of the library separately (where each version was built for a specific environment/configuration).<span id="more-369"></span><br />
<h2>Problem: What’s the best way to share code across iPhone projects?</h2>If you want to reuse/share code across different iPhone applications, you only have two options (that I’m aware of):<br />
<ol><li>Copy all of the source code from the “shared” library into your own project</li>
<li>Keep the shared library code in a separate Xcode project and use it to build static libraries (e.g., libSomeLibrary.a, also referred to as “archive files”) that can be referenced by your project and used via static linking.</li>
</ol><div style="float: right; padding-left: 15px;"><ins style="border: medium none; display: inline-table; height: 250px; margin: 0pt; padding: 0pt; position: relative; visibility: visible; width: 250px;"><br />
</ins> </div>The first option, copying the files, should be avoided when possible since it’s inherently redundant and contrary to the goal of keeping “common code” modular and atomic. It’s a much better idea to put the code in a <i><b>static library</b></i> since, as mentioned in the introduction, dynamic linking to custom libraries/frameworks isn’t allowed by Apple when it comes to iPhone apps. If you’re not sure how to put your code in a static library, I’d suggest taking a look at <a href="http://www.stormyprods.com/blogger/2008/11/using-static-libraries-with-iphone-sdk.html" target="_blank">this tutorial</a> on the Stormy Productions blog.<br />
So we’ve established that the second option is preferable, but there’s a catch: you’ll need to build and distribute multiple versions of the static library–one for each runtime environment and build configuration. For example, you would need to build both “release” and “debug” versions of the library for the Simulator, as well as other pairs for the iPhone or iPod device itself. How can we avoid manually pre-building and managing separate .a files?<br />
<h2>Solution: Static libraries that are built on-demand via Xcode cross-project references</h2>The trick to avoid pre-building static libraries for each environment is to use an Xcode “cross-project reference” so that those libraries are built dynamically (i.e., when you build your own app) using your app’s current build configuration. This allows you to both reuse shared source code <i><b>and</b></i> avoid the headache of managing multiple versions of the library. Here’s how it works at a high level:<br />
<ol><li>The shared code lives in its own Xcode project that, when built, results in one or more static libraries.</li>
<li>You create an Xcode environment variable with a path to the directory that contains the static library’s *.xcodeproj file.</li>
<li>All iPhone apps that need the static library will use the aforementioned environment variable to <i><b>reference</b></i> the library’s Xcode project, including any static library in that project and the related header files.</li>
<li>Each time you build your project for a specific configuration/runtime environment, the shared project library will also be built for that config/environment–if it hasn’t already–and linked with your executable.</li>
</ol>In addition to solving the main problem (reusing code and avoiding management of multiple library versions), there are a couple of nice benefits to this strategy. First, if you make changes to the shared library source code, those changes will immediately be included the next time you build your own project (via the cross-project reference). Second, you can modify the Xcode environment variable to point to different versions of any project. For example, you might have separate directories for “somelibrary-1.0″ and “somelibrary-2.0″; as you’ll see in the detailed solution instructions, it’s easy to modify the environment variable and switch your project to a different version of “somelibrary.”<br />
<h3>Other Solutions</h3><h4>zerg-xcode</h4>Victor Costan has developed a slick command-line tool called “<a href="http://github.com/costan/zerg_xcode/tree/master" target="_blank">zerg-xcode</a>” which helps you copy the source code from one Xcode project (i.e., a static library project) into another Xcode project. In addition to physically copying the files, it inserts the targets from the “library” project into your “app” project. If the library project changes, you simply run zerg-xcode again with the approriate commands to sync the files and targets. Some people may find this tool very useful; my personal preference, however, is to avoid making any copies of the source code files and stick to Xcode’s built-in “cross-project reference” mechanism.<br />
<h4>“Fat” Universal Binary</h4>Another approach is to “bundle” two versions of a static library into a single file, referred to as a “fat” universal binary (see <a href="http://latenitesoft.blogspot.com/2008/10/iphone-programming-tips-building-unix.html" target="_blank">this post</a> on the Latenitesoft blog for an example). More specifically, one version of the library would be for the i386 architecture (i.e., the Simulator) and the second for the ARM architecture (i.e., the phone). This may be a perfectly fine solution for you if you really only need two versions, or if the source code for the library is kept private. That said, you’re still left with the task of maintaining pre-built versions of the libraries (plus the extra work of bundling them into the single file). In addition, I’m not sure that you can bundle more than two versions of the library into the binary (e.g., iPhone “release” and Simulator “release”, but not iPhone “debug” and Simulator “debug”).<br />
<h2>How to Implement the Cross-Project Reference Solution</h2>The instructions for setting up cross-project references to shared static libraries can be split into two parts:<br />
<ul><li>Part 1: Global Xcode Settings</li>
<li>Part 2: Project-Specific Settings</li>
</ul>Also, I’ll be using an example in the instructions to help illustrate things. A suitable example would be an application that needs to use a shared static library from a separate project. In this case, I’ll use a sample iPhone app called “<a href="http://groups.google.com/group/cocos2d-iphone-discuss/web/sample-games" target="_blank">Game Skeleton</a>” (by Matt Sephton) that depends on a static library called <a href="http://code.google.com/p/cocos2d-iphone/" target="_blank">libcocos2d.a</a> (which is part of an open source project called Cocos2d-iphone).<br />
<div class="note"><b>Note</b>: If it wasn’t already clear, cross-project referencing is a standard Xcode feature and is actually suggested by Apple in the official “<a href="http://developer.apple.com/DOCUMENTATION/DeveloperTools/Conceptual/XcodeProjectManagement/000-Introduction/introduction.html" target="_blank">Xcode Project Management Guide</a>” documentation. You can certainly get some great bits of info from Apple’s guide, but as you’d expect, it’s a high-level document (hence my thinking that this tutorial could be helpful for others).</div><h3>Part 1: Global Xcode Settings</h3>The first step in getting your Xcode project to use cross-project referencing is to configure a couple of things that aren’t specific to any one project (i.e., global settings).<br />
<h4>Set up a <i><b>shared</b><b> build output </b></i><b>directory</b> that will be shared by all Xcode projects.</h4><div class="wp-caption alignright" id="attachment_371" style="width: 477px;"><img alt="Screenshot showing how the Xcode preference dialog and how to configure Xcode to use a global build output directory." class="size-full wp-image-371" height="211" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_global_build_dir.jpg" title="Screenshot: Xcode Global Build Output Settings" width="467" /><br />
<div class="wp-caption-text"><br />
</div><div class="wp-caption-text">Screenshot showing how the Xcode preference dialog and how to configure Xcode to use a global build output directory.</div></div><ol><li>With Xcode open, select “Xcode > Preferences” from the menubar.</li>
<li>Select the “Building” tab.</li>
<li>Set “Place Build Projects in” to “Customized location” and specify the path to the common build directory you created.</li>
<li>Set “Place Intermediate Build Files in” to “With build products.”</li>
</ol><span style="text-decoration: underline;">Why is this necessary?</span><br />
A brief explanation of why this is necessary might be helpful for some people. When you build your app (i.e., Xcode project) Xcode generates one or more “products” (object files, libraries, etc.) in the project’s own build output directory, by default; it will then “look” inside this directory when it comes time to link everything together and make an executable, for example.<br />
Once you start using cross-project references, you’ll essentially be building more than one project. However, Xcode will still only look in the immediate project’s build output directory for libraries. Apple therefore recommends using a shared build output directory for cross-project references (see the last paragraph in the “<a href="http://developer.apple.com/DOCUMENTATION/DeveloperTools/Conceptual/XcodeProjectManagement/040-Files_in_Projects/project_files.html#//apple_ref/doc/uid/TP40002666-CJBJHJCJ" target="_blank">Referencing Other Projects</a>” section of “Xcode Project Management Guide: Files in Projects”). This ensures that Xcode will always be able to find products from other projects builds.<br />
<span style="text-decoration: underline;">Will a shared build output directory cause problems?</span><br />
I’ve had some questions from folks about whether or not using a shared build output directory causes problems. While I’m certainly not an authority on building with Xcode, I can say that in four months of using this technique (with several projects and a few different shared libraries) I’ve not had any problems (such as a “debug” build resulting in a “release” version of your library being overwritten, etc.).<br />
Apple’s Xcode documentations clearly states that “Within the build directory, Xcode maintains separate subdirectories for each build configuration defined by the project” (see the “<a href="http://developer.apple.com/DOCUMENTATION/DeveloperTools/Conceptual/XcodeProjectManagement/070-Building_Products/building.html#//apple_ref/doc/uid/TP40002693-SW10" target="_blank">Build Locations</a>“ section of “Xcode Project Management Guide: Building Products”). For example, I have a custom logging library that is used by multiple iPhone and OS X apps. The OS X versions of the *.a file show up in “Release” and “Debug” sub-directories within the common build output folder, the simulator versions in “Release-iphonesimulator” and “Debug-iphonesimulator”, and finally the device versions in “Release-iphoneos” and “Debug-iphoneos.” In other words, none of the builds seem to be overwriting each other.<br />
<h4>Add a “Source Tree” variable that Xcode can use to dynamically find the static library project.</h4>“Source Tree settings” are basically Xcode environment variables that hold paths to directories on the file system; this allows us to make the cross-project references flexible and avoid hard-coded paths.<br />
<br />
<div class="wp-caption alignnone" id="attachment_415" style="width: 505px;"><img alt="Screenshot showing the "Source Tree" settings tab within Xcode preferences." class="size-full wp-image-415" height="262" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_sourcetreevar.jpg" title="Screenshot: Xcode Preferences, "Source Tree" tab" width="495" /><br />
<div class="wp-caption-text"><br />
</div><div class="wp-caption-text">Screenshot showing the "Source Tree" settings tab within Xcode preferences.</div></div><ol><li>Again, open the Xcode preferences.</li>
<li>Select the “Source Trees” tab.</li>
<li>Create a new Source Tree variable by clicking on the “+” button and filling in the columns. The screenshot above shows that we’re using “COCOS2D_SRC” for the cocos2d-iphone variable name and that it points to “/Users/clint/dev/cocos2d-iphone.googlecode.com/release-0.5.3″.<i><b>Tip:</b></i> <i>avoid using special characters in the actual file path (i.e., stick to alphanumeric characters, underscores, and hyphens); this path will be used as a “Search Path” and Xcode seems to have problems with search paths that use characters like an ampersand (&). </i></li>
</ol><h3>Part 2: Project-Specific Settings</h3>Once you’ve got Xcode configured to use a global build output directory and have a “Source Tree” variable pointing at your shared project, you’re ready to set up the cross-project reference, dependencies, etc.<br />
<h4>Set Up the Cross-Project Reference, Header File Search Paths, and Static Library Linking</h4><ol><li>Open your project in Xcode.</li>
<li>In the “Groups & Files” pane of Xcode, select your project root and hit Option+Cmd+A (add to project).</li>
<li>Find the Xcode project package for the project that contains the shared library. Using our example, we’ll select the Cocos2d-iphone Xcode project (cocos2d-port.xcodeproj): </li>
<li> </li>
</ol><ol><li><div class="wp-caption alignnone" id="attachment_419" style="width: 457px;"><img alt="Screenshot showing a second Xcode project file being selected so that we can add a reference to it." class="size-full wp-image-419" height="319" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_add_projectref.jpg" title="Screenshot: Adding Cross-Project Reference in Xcode" width="447" /><br />
<div class="wp-caption-text">Screenshot showing a second Xcode project file being selected so that we can add a reference to it.</div></div></li>
<li>When the “Add to Project” dialog is displayed, use the same settings displayed in the screenshot below and click the “Add” button.<br />
<i><b>Important: do NOT check the “Copy items” box.</b></i> <div class="wp-caption alignnone" id="attachment_421" style="width: 414px;"><img alt="Screenshot showing which "add to project" options are selected when adding a cross-project reference in Xcode." class="size-full wp-image-421" height="318" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_addproject-1.jpg" title="Screenshot: Xcode Settings for Cross-Project "Add to Project"" width="404" /><br />
<div class="wp-caption-text">Screenshot showing which "add to project" options are selected when adding a cross-project reference in Xcode.</div></div></li>
<li>After you click the “Add” button the project will appear as a “sub-project.” In our Cocos2d-iphone example, it looks like this: <div class="wp-caption alignnone" id="attachment_400" style="width: 261px;"><img alt="Screenshot showing how the Cocos2d-iphone Xcode project appears as a "sub project" once it has been added to the main "Skeleton" project." class="size-full wp-image-400" height="213" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_subproject.jpg" title="Screenshot: Xcode Subproject" width="251" /><br />
<div class="wp-caption-text">Screenshot showing how the Cocos2d-iphone Xcode project appears as a "sub project" once it has been added to the main "Skeleton" project.</div><div class="wp-caption-text"><br />
</div></div>Remember that you have <i><b>not</b></i> imported a physical copy of the second project–it’s a reference.<br />
</li>
<li>When the cross-project reference appears select it and hit Cmd+i. Then change “Path Type” to be <i><b>relative</b></i> to the environment variable you set up in Part 1. In the example below, we’re using the COCOS2D_SRC variable: <div class="wp-caption alignnone" id="attachment_404" style="width: 456px;"><img alt="Screenshot showing the Xcode "Project Info" dialog for a project added via cross-project reference." class="size-full wp-image-404" height="211" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_projectref_relativetopath-1.jpg" title="Screenshot: Xcode "Project Info" Dialog" width="446" /><br />
<div class="wp-caption-text"><br />
</div><div class="wp-caption-text">Screenshot showing the Xcode "Project Info" dialog for a project added via cross-project reference.</div></div></li>
</ol><h4>Configure the Library Dependencies, Linking, and Header Files</h4><ol><li>In the “Groups & Files” pane of Xcode, under “Targets”, select your main app target and hit Cmd+i. Then select general tab and add the static library(ies) your app needs from the shared project by clicking the “+” button under “Direct Dependencies”. In our example, we’ve added the “Chipmunk” and “cocos2d” libraries which are both built from the Cocos2d-iphone project: <div class="wp-caption alignnone" id="attachment_406" style="width: 486px;"><img alt="Screenshot showing an Xcode executable target being configured to depend on static libraries that are built from a cross-project reference." class="size-full wp-image-406" height="280" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_crossproject_dependencies.jpg" title="Screenshot: Xcode Target Dependencies on Cross-Project Libraries" width="476" /><br />
<div class="wp-caption-text"><br />
</div><div class="wp-caption-text">Screenshot showing an Xcode executable target being configured to depend on static libraries that are built from a cross-project reference.</div><div class="wp-caption-text"><br />
</div></div></li>
<li>Click on the build tab and scroll down to the “search paths” section</li>
<li><i><b>Important: If a hard-coded path to your shared project appears in the “Library Search Paths” field, delete it. This can be done by double-clicking the field and using the “-” button.</b></i></li>
<li>Double-click on blank area next to “User header search paths”. Then click on the “+” button, check the recursive checkbox, and type in the Xcode environment variable that points to your shared project directory, surrounded by $(). The example screenshot below shows $(COCOS2D_SRC) being used: <div class="wp-caption alignnone" id="attachment_409" style="width: 584px;"><img alt="Screenshot showing how to configure the Xcode "User Header Search Paths" for a library that is being included via cross-project reference." class="size-full wp-image-409" height="306" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_headersearchpaths_crossprojectref.jpg" title="Screenshot: User Header Search Paths for Dependencies in Xcode" width="574" /><br />
<div class="wp-caption-text">Screenshot showing how to configure the Xcode "User Header Search Paths" for a library that is being included via cross-project reference.</div><div class="wp-caption-text"><br />
</div></div></li>
<li>When you click OK and go back to the Build tab, the “user header search paths” text field should show an absolute path to your shared project directory. In our example, $(COCOS2D_SRC) expanded to the actual path and ends with “**” to show that the search will be recursive: <div class="wp-caption alignnone" id="attachment_411" style="width: 631px;"><img alt="Screenshot showing how an Xcode environment variable will be dynamically expanded to the actual, absolute path once entered using the $() notation." class="size-full wp-image-411" height="188" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_headersearchpaths_envvar_expanded.jpg" title="Screenshot: Xcode Environment Variable Expanded to Full Path" width="621" /><br />
<div class="wp-caption-text"><br />
</div><div class="wp-caption-text">Screenshot showing how an Xcode environment variable will be dynamically expanded to the actual, absolute path once entered using the $() notation.</div><div class="wp-caption-text"><br />
</div></div></li>
<li>Finally, click and drag the static libraries from underneath the cross-project reference to “Targets > {your target} > Link Binary with Libraries.” This ensures that that the .a files will be passed to the linker when you do the build. Here’s a sample screenshot from our example app: <div class="wp-caption alignnone" id="attachment_412" style="width: 313px;"><img alt="Screenshot showing how to link your executable to the static libraries via cross-project reference in Xcode." class="size-full wp-image-412" height="427" src="http://www.clintharris.net/_wpress/wp-content/uploads/2009/03/screenshot_xcode_linkstaticlibs.jpg" title="Screenshot: Linking to Static Libraries via Cross-Project Reference" width="303" /><br />
<div class="wp-caption-text">Screenshot showing how to link your executable to the static libraries via cross-project reference in Xcode.</div></div></li>
</ol><h2>Summary</h2>To recap, if you need to share code across different iPhone projects I suggest 1) putting the shared code in its own “static library” Xcode project and 2) using a cross-project reference so that you can build the library with your own app as needed. The verboseness of this tutorial might give you the impression that setting this up is a lot of work; it’s not, really, especially if you do it more than once (which is likely, considering that the goal here is to share code across <i>multiple</i> projects). I’ve been using this approach for about four months with several projects and it’s definitely saved me a lot of time. Finally, there might be a better strategy that I’m not aware of; feedback and suggestions for alternate solutions are certainly welcome.<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com1tag:blogger.com,1999:blog-4167037314987902278.post-18879811648933383382010-11-26T01:58:00.000-08:002010-12-09T01:03:44.222-08:00App Store Rejection Reasons<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<div class="entry"><span style="font-size: 14px; font-weight: bold;">Bugs</span><br />
One of the larger categories of App Store rejections is probably plain bugs. If the app crashes during the review testing it will be rejected. Test your app thoroughly before you submit it. Make sure you test it on multiple devices, different OS versions and specifically under varying network conditions. Since all developers hate testing their own code, write unit test code for your regression testing.<br />
<br />
<h3>HIG</h3>Discoverability is a problem with touch interfaces. (Hover with your finger above a button and see if you get any hints as to what the button does…) Users know how UI:s work by convention and they have been trained by Apple’s built-in apps. If you use a button image or a UI metaphor in an unconventional way, you will confuse users. This is why adherence to the HIG is so important, and why Apple is so nitpicky in enforcing it.<br />
<br />
<b>Here are some concrete examples of HIG violations:</b><br />
<ul><li>Tapping an action button (a rectangle with an arrow coming out of it) must result in an action sheet where the user can select an action or cancel.</li>
<li>The same holds true for all built-in icons. Make sure that your app behaves exactly as Apple’s apps to when you tap one of these icons.</li>
<li>Don’t leave activity indicators spinning forever. This can easily happen if you don’t trap errors properly.</li>
<li>TableViewCells must not have state, i.e. make sure that the highlight is removed when the selection action is done. If you use a UITableViewController rows are automagically cleared for you when the screen is shown. If you’re rolling your own, add this to your code:</li>
</ul><pre class="c">- (void)viewWillAppear:(BOOL)animated
{
NSIndexPath *tableSelection = [self.tableView indexPathForSelectedRow];
[self.tableView deselectRowAtIndexPath:tableSelection animated:NO];
}</pre><h3>Lite Versions</h3>The rules surrounding Lite versions of apps are murky at best. I have not had any issues with this, but here are some items I’ve heard from other developers:<br />
<ul><li>A Lite app cannot appear to be crippled. For example visually disabled buttons or sections of the app are not allowed.</li>
<li>You cannot prompt the user to upgrade to the full version.</li>
<li>You cannot display the price of the full version inside the Lite app.</li>
</ul><br />
<h3>Internet Connectivity</h3>If your application depends on Internet connectivity and it’s not available, then you must display a message to the user. This is actually trickier than it sounds to implement in your code. Most people base their connectivity checks on Apple’s Reachability code, which is using that sample code for the wrong purpose. If you need to get data from a specific server, then try to download some data from that domain. If that’s successful then you have the necessary connectivity. A special case to test for is WiFi hotspots that require a login to get online. Go to your nearest Starbucks and test your app. The Starbucks WiFi hotspots also have the additional quirk of allowing access to the apple.com domain, which may be what your connectivity test uses if you just copied Apple’s sample code.<br />
It is my experience that Apple always tests applications under no connectivity conditions. Save yourself some approval time and test this yourself first.<br />
<br />
<h3>Excessive Bandwidth Usage Over Cellular Networks</h3>“Bandwidth hogs” was on Apple’s original list of forbidden fruit when the SDK was introduced. Unfortunately they have never defined exactly what the limits are. If you streaming or downloading a lot of data, make sure your application knows what type of network is in use and it has the ability to throttle or switch to a stream with a lower bit rate if necessary.<br />
<br />
<h3>Device Capabilities</h3>There are a few differences between the various iPhone and iPod Touch generations. Don’t assume that the device running your app has a particular capability. In one app I had a settings screen where the user could turn off vibrations. That setting obviously has no effect on an iPod Touch, and the app was thus swiftly rejected.<br />
<br />
<h3>Private API:s</h3>Calling private API:s has always been verboten. Some developer have tried to argue that some API components are “more private” than others. For example it seems less nefarious to pass in an undocumented parameter value to a public API than linking to a private framework. In the long run I think such distinctions are futile. If your business depends on your app being approved, then stay clear of anything that is not documented as official by Apple.<br />
In the beginning a lot of apps got away with breaking this rule. Now Apple has more sophisticated scripts that scan your code looking for violations.<br />
One particular API has been the source of some amusement: the private Coverflow API. Several developers, myself included, have had apps rejected for using this API when we in reality had spent a lot of time and effort in building a reasonable implementation of Apple’s coverflow user experience. I guess we should be flattered that Apple mistook our implementation for their own.<br />
<br />
<h3>No Interpreted Code</h3>You cannot create an app that downloads and executes code that was not present in the app bundle submitted to Apple. This rule puts the kibosh on emulators (NES, C64, etc) and effectively kills alternative web browsers (you would want to run JavaScript in the browser) as well as Flash.<br />
<br />
<h3>Limited Functionality</h3>This was a common rejection before the “fart category” was approved. In the beginning of the App Store it was not uncommon to see apps that simply opened a web view to a company’s web site. The goal was to get traffic to the web site, with the idea that competing with a few hundred apps was much easier than competing with millions of other web sites. With 140k apps, being noticed in the App Store is probably as difficult as on the web. In any case, Apple will reject simple UIWebView apps without any additional functionality.<br />
<br />
<h3>Duplicates Functionality</h3>This is a tricky one. There have been several high-profile cases where an app has been rejected for duplicating functionality of a built-in app. But having built a <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298505665&mt=8">web browser app</a>with parental controls that was approved without any major delay, I don’t know where the line goes.<br />
<br />
<h3>Contests and Sweepstakes</h3>Apple now allows both contests and sweepstakes within applications. The new rule, found in section 3.3.17, states, “Your Application may include promotional sweepstake or contest functionality provided that You are the sole sponsor of the promotion and that You and Your Application comply with any applicable laws,” adding that developers must “clearly state in binding official rules for each promotion that Apple is not a sponsor of, or responsible for conducting, the promotion.”<br />
<br />
<h3>Handling of User Data</h3>If you collect any user information and that data is sent to a server then you need to explain to the user what is about to happen and give an option to opt out. This applies, for example, to highscore and leaderboard liets. And even if the information submitted is just a bogus name that the user enters specifically for this purpose.<br />
If your app uses Core Location for the sole purpose of serving ads or user tracking, then your app will be rejected. The use of Core Location needs to provide some benefit to the user. See Apple’s <a href="http://developer.apple.com/iphone/news/archives/2010/february/#corelocation%23corelocation">announcement</a>.<br />
<br />
<h3>Copyrighted Content</h3>It goes without saying that you must have the rights to the content that you include in your apps. Recently Apple has begun checking and enforcing this more seriously. You need to know your copyright and trademark law to stay clear of violations. For example there have been several cases where developers have replicated old console games on the iPhone and the original owners of the game have complained to Apple resulting in the removal of the app from the App Store.<br />
<br />
<h3>Use of Trademarked Images</h3>If you display an image of an iPhone, or any other Apple product, inside your app it will be rejected unless you have received written approval from Apple to use that image. What exactly constitutes iPhone likeness? Some developers have reported that removing the home button circle is enough.<br />
<br />
<h3>Objectionable Content</h3>This is another big and sticky one without any clear guidelines from Apple. Here’s my experience:<br />
<ul><li>Nudity is off limits, even with a 17+ rating.</li>
<li>For women in bikinis, images are rejected seemingly at random. One reviewer will object to a particular image and pass others, the next reviewer will find an objectionable image in the batch that the first reviewer passed. And on it goes.</li>
<li>Anything related to politicians will most likely be rejected.</li>
</ul>The app reviewers seem to go to great lengths to find objectionable content by explicitly searching for swear words, or seeking out specific ebooks to download which may contain anything objectionable.<br />
Another source of hilarity is content that actually doesn’t exist in the app. Remember the Twitter client that was rejected for displaying a trending hashtag that contained a bad word? To the app reviewers defense I must say that it can often be very difficult to know what content comes from the app itself and what is coming from a different source. The result seems to be that the source doesn’t matter. If it’s displayed within your app, you’re responsible for it. See also the next section about web views.<br />
<br />
<h3>UIWebViews</h3>If your application has a web view that allows unrestricted access to the Internet where scary things lurk, then you are automatically slapped with a 17+ rating. Why the built-in Safari app is not consequently shielded from minors is a mystery. But those are apparently the rules.<br />
Now unless you are building a web browser, it seems unnecessary for you to allow full and unrestricted access to the Internet from within your app.<br />
<br />
<h3>Transactions Outside The App Store</h3>Apple doesn’t want you to conduct any commerce outside the App Store. Before In-App Purchasing was available we developed an app that allowed the user to purchase additional credits using a third party payment service. That feature had to be removed. Another of our clients has a calling card type app. If you have a calling card you typically have an account that you may want to check the balance of, and you may want to add more money to it using your credit card. It took several submissions to get the wording surrounding these features to Apple’s liking. In the end all references to an account were removed and all links to the vendor’s web site opened Safari instead of an internal web view.<br />
<br />
<h3>Price Information</h3>Do not display the price of an application inside your app or in your application description. The very reasonable explanation for this is that App Store prices/currencies vary from country to country.<br />
<br />
<h3>App Icon and App Store Image</h3>The 57×57 application icon and the 512×512 App Store Image must depict the same thing.<br />
<br />
<h3>Application Description</h3>This doesn’t have to do with development per se. But when write the App Store description make sure that you are describing the application correctly. If you describe a feature that is not there, then you will be rejected.<br />
The same is true for the update notes. If your app update doesn’t exactly address the things you list in the “what’s new in this version” notes, you will be rejected.<br />
<br />
<h3>App Store Keywords</h3>The keywords you enter for your application have to be relevant, <i>as Apple sees it</i>. If your app is about football, don’t use a basketball keyword just because you think there’s an overlap in the demographics. And don’t use trademarked words, e.g. ESPN, or names of other App Store apps.<br />
The punishment is that you’re app will be rejected, not just the description. You have to resubmit the binary and go to the end of the line.<br />
<br />
<h3>Updates Are Reviewed As New Apps</h3>Just because your app was approved once doesn’t mean that the original features are “safe” when you submit an update. It appears that all updates are reviewed as if they were brand new apps. A HIG violation that has been approved 5 times may be caught and rejected on your 6th app update.<br />
<br />
<h3 style="font-size: 1.17em;">iPad Specific Rejections</h3><h4>Support all four orientations</h4><div><div>The iPad Human Interface Guidelines state that an iPad application should be able to run in all orientations. There are certain applications that need to run in the portrait orientation, it would be appropriate to support at least both variants of this orientation in your application. Supporting all four orientations, each with unique launch images, provides the best user experience and is recommended.</div></div><span style="font-size: 12px; font-weight: bold;">Popovers</span><br />
Do not launch one popover from within another popover. The iPad Human Interface Guidelines state that only one popover element should be visible onscreen at a time.<br />
<br />
<h3>More Advice</h3>Unfortunately this list is not complete, as only Apple knows the extent of the hidden rules. Also, with a few exceptions that are anecdotal or widely known, the items on this list are rejections that I and my colleagues have personally experienced.<br />
Here is a list of tips from Apple: <a href="https://developer.apple.com/iphone/news/appstoretips/">App Store Submission Tips</a>. It only contains a handful of items at the moment, but it’s a good sign from Apple. Since this should count as the official word from Apple, I sincerely hope that this list will grow to encompass all the “hidden” rules that have been painstakingly discovered by developers over time.<br />
Until that happens, here are a couple of good resources with app rejection advice from other developers:<br />
<ul><li><a href="http://apprejections.com/">App Rejections</a></li>
<li><a href="http://www.apprejected.com/">www.apprejected.com/</a></li>
<li><a href="http://boredzo.org/killed-iphone-apps/">boredzo.org/killed-iphone-apps/</a></li>
<li><a href="http://appreview.tumblr.com/">appreview.tumblr.com/</a></li>
<li><a href="http://www.mobileorchard.com/avoiding-iphone-app-rejection-from-apple/">www.mobileorchard.com/avoiding-iphone-app-rejection-from-apple/</a></li>
<li><a href="http://www.mobileorchard.com/avoiding-iphone-app-rejection-part-2/">www.mobileorchard.com/avoiding-iphone-app-rejection-part-2/</a></li>
<li><a href="http://iphone-rejectdb.appspot.com/">iphone-rejectdb.appspot.com/</a></li>
</ul>And some good humor:<br />
<ul><li><a href="http://daringfireball.net/2009/05/diary_of_an_app_store_reviewer">Excerpts From the Diary of an App Store Reviewer</a></li>
<li><a href="http://www.geekculture.com/joyoftech/joyarchives/1151.html">How Apple decides whether or not to put an app on the App Store</a></li>
<li><a href="http://www.juliansmith.tv/2010/01/one-bad-app/">One Bad App</a></li>
<li><a href="http://geekandpoke.typepad.com/geekandpoke/2010/04/ipray-or-inscrutable-part-ii.html">iPray</a></li>
</ul><b>UPDATE:</b> Apple has finally published the <a href="http://developer.apple.com/appstore/guidelines.html">App Store Review Guidelines</a>. I will keep this page live for historic reasons, but hopefully it will not need to be updated any more since Apple describes their guidelines as a living document that will be amended over time as they craft new rules.</div><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com1tag:blogger.com,1999:blog-4167037314987902278.post-4402862882901751012010-11-26T01:53:00.000-08:002010-12-09T01:03:43.588-08:00How to add multiple static library files with different architectures to Xcode<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
When you work with a static library (e.g. libCoolCode.a) for an iPhone project in Xcode, you can either have a fat binary that contains code for both the iPhone simulator and the iPhone device in the same file, or you may have two separate files that you need to add to Xcode.<br />
Adding a single static library to Xcode is trivial. Here are the step by step instructions for the latter case.<br />
<h3>1. Add the files to Xcode</h3>Use the normal Add > Existing Files… to add both the header files and the library files to your project. The result should look something like this:<br />
<img alt="LibraryAndHeaderFilesAddedToXcode.png" border="0" height="156" src="http://iphoneincubator.com/blog/wp-content/uploads/2010/09/LibraryAndHeaderFilesAddedToXcode.png" width="211" /><br />
<h3> </h3><h3>2. Add the header files to the search path</h3>A static library comes with one or more header files (.h) that you need to add to your project build settings. (This step is the same for a single library file as for multiple files.)<br />
Open the build settings tab and find the “Header Search Paths” entry, and add the path to the directory with the header files.<br />
<br />
<img alt="AddHeaderSearchPathToXcodeBuildSettings.png" border="0" height="272" src="http://iphoneincubator.com/blog/wp-content/uploads/2010/09/AddHeaderSearchPathToXcodeBuildSettings.png" width="490" /><br />
<br />
For this particular library there’s a model directory under the headers directory which also contains headers files. That’s why the Recursive checkbox is checked. The double quotes around the path are needed to handle paths with spaces.<br />
If you try to build the project for the simulator at this point you’ll probably get a compiler warning like this:<br />
<pre>file was built for unsupported file format which is not the architecture being linked (i386)</pre><h3> </h3><h3>3. Remove the library files from the build target</h3>Open the Targets tab and the target of your project and you’ll see that the library files you just added were also added to the list of libraries to link with.<br />
<img alt="LibraryFilesInTargetLinkFolder.png" border="0" height="207" src="http://iphoneincubator.com/blog/wp-content/uploads/2010/09/LibraryFilesInTargetLinkFolder.png" width="259" /><br />
<br />
Delete these two entries.<br />
You may also have to delete these entries from the build settings. In the build settings tab find the Library Search Paths entry and delete the two entries.<br />
<br />
<img alt="DeleteLibrarySearchPathInXcode.png" border="0" height="272" src="http://iphoneincubator.com/blog/wp-content/uploads/2010/09/DeleteLibrarySearchPathInXcode.png" width="490" /><br />
<br />
That will get rid of the compiler warning above, but the linker will complain since the required libraries are no longer linked.<br />
<br />
<h3>4. Add the libraries as other linker flags</h3>Again go to the build settings tab and now find the Other Linker Flags (OTHER_LDFLAGS) entry.<br />
Highlight the Other Linker Flags entry and click on the tool drop down button at the bottom of the window.<br />
<br />
<img alt="XcodeBuildSettingsToolsDropDownMenu.png" border="0" height="119" src="http://iphoneincubator.com/blog/wp-content/uploads/2010/09/XcodeBuildSettingsToolsDropDownMenu.png" width="235" /><br />
<br />
Select Add Build Setting Condition from the drop down menu. This will add a new line under the Other Linker Flags entry. Change the first drop down from Any SDK to Any iOS Simulator. Leave the second drop down as Any Architecture. In the value field enter the path and name of the library file built for the simulator. Repeat this step for the device build, selecting Any iOS Device. The result should look similar to this (your paths will of course be different):<br />
<br />
<img alt="OtherLinkerFlagsConditionalBuildSettings.png" border="0" height="40" src="http://iphoneincubator.com/blog/wp-content/uploads/2010/09/OtherLinkerFlagsConditionalBuildSettings.png" width="600" /><br />
<br />
Your project should now compile and run for both the simulator and the device.<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0tag:blogger.com,1999:blog-4167037314987902278.post-50423512390845915702010-10-27T05:35:00.000-07:002010-12-09T01:04:04.929-08:00UINavigationBar Back Button with images<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
This is a topic that I have noticed on numerous iPhone development forums and since I’ve had to address this in multiple apps that I’ve worked on in the past, I thought it would be a good topic to share some info on. The default behavior of the navigation controller is to provide a back button with the title of the previous view controller. This is fine and dandy if you have short titles and that’s the behavior your looking for but what if you wanted to create a home button similar to the Facebook app or for that matter, an image that acts like a button but doesn’t look like one.<br />
We will start with the Facebook style Home button. To reproduce the following:<br />
<br />
<a href="http://michaelvpark.com/wp-content/uploads/2010/01/facebook-navbar.png"><img alt="" class="aligntop size-medium wp-image-71" height="88" src="http://michaelvpark.com/wp-content/uploads/2010/01/facebook-navbar-300x88.png" title="facebook-navbar" width="300" /></a><br />
<br />
In the view controller that you want to add the home button to, your going to need to add a cancel method to pop your view controller:<br />
<br />
<pre class="c++:showcolumns" name="code">-(IBAction)cancel:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}</pre><pre class="c++:showcolumns" name="code"></pre>Next you will need to add your custom home button with some sort of image, in this case we are using an image called “home-button.png”:<br />
<br />
<pre class="c++:showcolumns" name="code">- (void)viewDidLoad {
[super viewDidLoad];
// Add Home Button
UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
initWithImage:[UIImage imageNamed:@"home-button.png"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(cancel:)] autorelease];
self.navigationItem.leftBarButtonItem = cancelButton;
}</pre><pre class="c++:showcolumns" name="code"></pre>And that’s it. You’ll need this in each view controller that is on top of your home view controller.<br />
Next we will recreate the following:<br />
<br />
<a href="http://michaelvpark.com/wp-content/uploads/2010/01/kt-navbar.png"><img alt="" class="aligntop size-medium wp-image-72" height="197" src="http://michaelvpark.com/wp-content/uploads/2010/01/kt-navbar-300x197.png" title="kt-navbar" width="300" /></a><br />
<br />
In this case, we are using an image as the leftbarbuttonitem. We do so by creating our cancel method in the view controller that you want to add the home or back image to.<br />
<br />
<pre class="c++:showcolumns" name="code">-(IBAction)cancel:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}</pre><pre class="c++:showcolumns" name="code"></pre>Next we will add the image “back-image.png” as our back button and size up the button:<br />
<br />
<pre class="c++:showcolumns" name="code">- (void)viewDidLoad {
[super viewDidLoad];
// Add Back Bar Button
UIButton *home = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *homeImage = [[UIImage imageNamed:@"back-image.png"]
stretchableImageWithLeftCapWidth:10 topCapHeight:10];
[home setBackgroundImage:homeImage forState:UIControlStateNormal];
[home addTarget:self action:@selector(cancel:)
forControlEvents:UIControlEventTouchUpInside];
home.frame = CGRectMake(0, 0, 99, 35);
UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
initWithCustomView:home] autorelease];
self.navigationItem.leftBarButtonItem = cancelButton;
}</pre><pre class="c++:showcolumns" name="code"></pre>And that’s it! One nice benefit to this is that you can perform additional processing in the cancel method if needed prior to popping to the previous controller.<br />
One last item to add is if you just want to change the text of the back button so that it’s different than the previous view controller’s title:<br />
<br />
<pre class="c++:showcolumns" name="code">UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle:@"Back"
style:UIBarButtonItemStylePlain
target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];</pre><br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com5tag:blogger.com,1999:blog-4167037314987902278.post-70938188901959223092010-10-27T05:31:00.000-07:002010-12-09T01:04:14.430-08:00Tutorial: iPhone SQLite Encryption With SQLCipher<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<br />
Mobile devices are notoriously difficult to secure. With a small footprint it is dangerously easy to leave your phone in the back of a taxi, or forget to pick it up from a table after dinner at a restaurant. iPhone and iPod Touch devices are no exception – most applications store their data in an easily readable format. Anyone with access to your device can browse through your personal information. Even worse, since the devices back up to your computer, any knowledgeable person with access to your workstation can read your data as well.<br />
This is balanced by immense convenience. An iPhone makes a perfect digital wallet: a single device with all your important information literally at your fingertips. When we set out to write <a href="http://www.zetetic.net/products/strip">Strip</a>, our iPhone Password Manager and Data Vault, we wanted to build a system that we could trust to store Passwords, Credit Card Numbers, Passport Identifiers, SSNs and bank account information. Most of the other applications in the App store used undocumented encryption or weaker field level security. We wanted to encrypt <span class="caps">EVERY</span> bit of Strip’s data on the device. Naturally the ideal approach would be to have the encryption managed transparently, so Strip didn’t need to know about the details.<br />
Enter <a href="http://zetetic.net/software/sqlcipher">SQLCipher</a>, a specialized build of the excellent <a href="http://sqlite.org/">SQLite</a> database that performs transparent and on-the-fly encryption. Using SQLCipher, an application uses the standard <a href="http://sqlite.org/">SQLite <span class="caps">API</span></a> to manipulate tables using <span class="caps">SQL</span>. Behind the scenes the library silently manages the security aspects, making sure that data pages are encrypted and decrypted as they are written to and read from storage. SQLCipher uses the widely trusted and peer-reviewed <a href="http://www.openssl.org/">OpenSSL</a> library for all cryptographic functions.<br />
SQLite is already the predominant <span class="caps">API</span> for persistent data storage on the iPhone so the upside for development is obvious. As a programmer you work with a stable and well documented <span class="caps">API</span>. All security concerns are cleanly decoupled from application code and managed by the underlying framework. The framework code of the SQLCipher and OpenSSL projects are both open source, so users can be confident that an application isn’t using insecure or proprietary security code.<br />
Using SQLCipher in an iPhone application is straightforward once you setup your project properly. The easiest way to integrate SQLCipher into an application is to use XCode project references as described here.<br />
<br />
<b>Get OpenSSL</b><br />
SQLCipher relies on OpenSSL for several encryption requirements including the <span class="caps">AES</span>-256 algorithm, pseudo random number generation, and <span class="caps">PBKDF2</span> key derivation. OpenSSL isn’t a framework that is usable directly on the iPhone so we will setup our project to build and link against it as a static library.<br />
Navigate to the <a href="http://www.openssl.org/source/">OpenSSL download page</a>. Download the source file of the latest stable version (0.9.8k as of this writing) and extract it to a folder on your system. Make a note of the source directory path for later.<br />
OpenSSL can be a tricky system to compile properly from source. It’s even more complex when you’re dealing with multiple target architectures, targeting i386 for the simulator but armv6 for a device. Luckily we’ve built a handy XCode project template to make it easy called openssl-xcode. The project actually relies on the OpenSSL configure and make system to build the libraries. However, it automatically detects the appropriate build settings for architecture (i386, ppc, arv6), build tools, and <span class="caps">SDK</span>. This makes it ideal for inclusion in an iPhone project. Just git clone or download <a href="http://github.com/sjlombardo/openssl-xcode">openssl-xcode</a> from GitHub and move the openssl.xcodeproj file into the OpenSSL source directory.<br />
<br />
<b>Get SQLCipher</b><br />
SQLCipher is a standalone package that includes the entire SQLite source distribution. You can git clone or download the latest version from the <a href="http://github.com/sjlombardo/sqlcipher">SQLCipher repository</a> on GitHub. Again, make note of the source directory path you use for later in the setup process.<br />
<br />
<b>XCode Setup</b><br />
SQLCipher uses project references to manage build dependencies and static linking. In order to allow linking you must setup your XCode environment to use a central build location. We will also need to configure Source Trees OpenSSL and SQLCipher respectively.<br />
<ol><li>Open XCode, Choose the XCode Menu, and then Preferences.</li>
<li>On the Building tab, Change the “Place Build Products In” to “Customized location” and pick a location for the build directory.</li>
</ol><img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/build-location.png" width="500" /><br />
<ol><li>Switch to the Source Tree tab.</li>
<li>Add a <span class="caps">SQLCIPHER</span>_SRC that references the path to the SQLCipher sourcecode</li>
<li>Add a <span class="caps">OPENSSL</span>_SRC to reference the path to the OpenSSL sourcecode</li>
</ol><img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/source-trees.png" width="500" /><br />
<br />
<b>Project Setup</b><br />
Now that we have XCode global preferences setup we will move on to the project configuration.<br />
<img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/add-reference.png" width="500" /><br />
Open your XCode application project, and click on the top level Project item. Hit option-command-a to add a resource. Navigate to the OpenSSL directory and choose the openssl.xcodeproj to add the reference. When the add resource window comes up make sure that “Copy items” is not checked, and add it to the appropriate target. Repeat the same, this time choose the sqlcipher.xcodeproj file in SQLCipher source directory.<br />
Let’s change the Path Types as a convenience to multi-developer teams. Using paths relative to the Source Trees we defined will allow each developer to place the SQLCipher and OpenSSL in any locations and the build will still work.<br />
<img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/relative-to-source.png" /><br />
<ol><li>Hit option-i on the sqlcipher.xcodeproj reference and change the Path Type to “Relative to <span class="caps">SQLCIPHER</span>_SRC”.</li>
<li>Hit option-i on the openssl.xcodeproj reference and change the Path Type to “Relative to <span class="caps">OPENSSL</span>_SRC” </li>
<li>Hit option-command-a to add another resource</li>
</ol>Now we will add build dependencies to ensure that the SQLCipher is compiled before the application code. Open the Info panel for your Application Target and Choose the General Tab. We will add two dependencies, one for OpenSSL crypto, and one for SQLCipher.<br />
<img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/add-dependency.png" /><br />
Then switch to the Build tab to add our source paths to the include directories to make relevant header files available. Make sure that the Configuration is set to “All Configurations”. Look for the “Header Search Paths” setting and add references to $(SQLCIPHER_SRC) and $(OPENSSL_SRC). Check “recursive” on both.<br />
<img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/header-search.png" width="500" /><br />
Finally, we will tell XCode to link against the built libraries. Expand the sqlcipher and openssl .xcodeproj references and select libsqlcipher.a and libcrypto.a. Drag and drop them on “Link Binary With Libraries” under your application target.<br />
<img class="frame" src="http://www.mobileorchard.com/wp-content/uploads/2009/06/link-with.png" /><br />
<br />
<b>Building SQLCipher</b><br />
At this point you should be able to build your XCode project without errors. Note that the first time you build your application for a particular architecture (Simulator for instance), it will take much longer than usual. This is because SQLCipher and OpenSSL are compiled from source for the specific architecture. You can keep track of the status under Build Results. Subsequent builds for the same platform will be much quicker since the libraries don’t need to be recompiled.<br />
<br />
<b>In Code</b><br />
Now that you’ve incorporated the SQLCipher library into your project you can start using the system immediately. Telling SQLCipher to encrypt a database is as easy as opening a database and using “PRAGMA key” or the sqlite3_key function.<br />
<pre>#import <sqlite3.h>
...
sqlite3 *db;
if (sqlite3_open(@"/path/to/database", &db) == SQLITE_OK) {
sqlite3_exec(db, "PRAGMA key = 'BIGsecret', NULL, NULL, NULL);
if (sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
// password is correct, or, database has been initialized
} else {
// incorrect password!
}
}</sqlite3.h></pre>The call to sqlite3_key or <span class="caps">PRAGMA</span> key should occur as the first operation after opening the database. In most cases SQLCipher uses <a href="http://en.wikipedia.org/wiki/PBKDF2"><span class="caps">PBKDF2</span></a>, a salted and iterated key derivation function, to obtain the encryption key. Alternately, can tell SQLCipher to use a specific binary key in blob notation (note that you must provide exactly 256 bits of key material):<br />
<pre>PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";</pre>Once the key is set SQLCipher will automatically encrypt all data in the database! If you don’t set a key then SQLCipher will operate identically to a standard SQLite database.<br />
Note: In the interest of brevity and clarity this section demonstrates the use of the API to set a passphrase and an encryption key using a static value. In a real application the passphrase or key data should be collected from an external source, like a “Secure” UITextField, and then passed to SQLCipher. An application should never hard-code its key, as this would be very easy to crack.<br />
<br />
<b>Verify</b><br />
After your application is wired up to use SQLCipher you should take a quick peek at the resulting data files to make sure everything is in order. An ordinary SQLite database will look something like the following under hexdump. Note that the file type, schema, and data are clearly readable.<br />
<pre>new-host-2:sqlcipher sjlombardo$ hexdump -C plaintext.db
00000000 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 |SQLite format 3.|
00000010 04 00 01 01 00 40 20 20 00 00 00 04 00 00 00 00 |.....@ ........|
...
000003b0 00 00 00 00 24 02 06 17 11 11 01 35 74 61 62 6c |....$......5tabl|
000003c0 65 74 32 74 32 03 43 52 45 41 54 45 20 54 41 42 |et2t2.CREATE TAB|
000003d0 4c 45 20 74 32 28 61 2c 62 29 24 01 06 17 11 11 |LE t2(a,b)$.....|
000003e0 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 |.5tablet1t1.CREA|
000003f0 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29 |TE TABLE t1(a,b)|
...
000007d0 00 00 00 14 02 03 01 2d 02 74 77 6f 20 66 6f 72 |.......-.two for|
000007e0 20 74 68 65 20 73 68 6f 77 15 01 03 01 2f 01 6f | the show..../.o|
000007f0 6e 65 20 66 6f 72 20 74 68 65 20 6d 6f 6e 65 79 |ne for the money|</pre>Fire up your SQLCipher application in simulator you can look for your database files under <code>/Users/<username>/Library/Application Support/iPhone Simulator/User/Applications/<hex app="" id="">/Documents</hex></username></code>. Try running hexdump on your application database. With SQLCipher you should get output that looks completely random, with no discerning characteristics at all:<br />
<pre>new-host-2:Documents sjlombardo$ hexdump -C encrypted.db
00000000 84 d1 36 18 eb b5 82 90 c4 70 0d ee 43 cb 61 87 |.?6.?..?p.?C?a.|
00000010 91 42 3c cd 55 24 ab c6 c4 1d c6 67 b4 e3 96 bb |.B00000020 8e df fa bc c3 9c 92 8a 4e 40 59 6f b5 95 f3 80 |.????...N@Yo?.?.|
...
00000bd0 91 16 9e 89 d9 4e ac f7 1c c9 d1 d7 aa bb a7 51 |....?N??.??ת??Q|
00000be0 dc 77 5c 6c de c6 d3 be 43 49 48 3e f3 02 94 a9 |?w\l??ӾCIH>?..?|
00000bf0 8e 99 ee 28 23 43 ab a4 97 cd 63 42 8a 8e 7c c6 |..?(#C??.?cB..|?|
00000c00</pre><pre></pre><b>Conclusion</b><br />
SQLCipher is an easy way to incorporate full database encryption into an iPhone application. For more information on SQLCipher and the underlying security features please check out the <a href="http://www.zetetic.net/software/sqlcipher">SQLCipher project site</a>. To see it in action please try <a href="http://www.zetetic.net/products/strip/its-strip">Strip</a> and <a href="http://www.zetetic.net/products/strip/its-striplite" title="free">Strip Lite</a> in the iTunes App Store!<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com1tag:blogger.com,1999:blog-4167037314987902278.post-48429512499634864342010-10-27T05:28:00.001-07:002010-12-09T01:04:22.254-08:00Core Data and Enterprise iPhone Applications – Protecting Your Data<script type="text/javascript">
var AdBrite_Title_Color = 'CC0000';
var AdBrite_Text_Color = '000000';
var AdBrite_Background_Color = 'C3D9FF';
var AdBrite_Border_Color = 'CCCCCC';
var AdBrite_URL_Color = '008000';
try{var AdBrite_Iframe=window.top!=window.self?2:1;var AdBrite_Referrer=document.referrer==''?document.location:document.referrer;AdBrite_Referrer=encodeURIComponent(AdBrite_Referrer);}catch(e){var AdBrite_Iframe='';var AdBrite_Referrer='';}
</script><br />
<span style="white-space: nowrap;"><script type="text/javascript">
document.write(String.fromCharCode(60,83,67,82,73,80,84));document.write(' src="http://ads.adbrite.com/mb/text_group.php?sid=1421822&zs=3436385f3630&ifr='+AdBrite_Iframe+'&ref='+AdBrite_Referrer+'" type="text/javascript">');document.write(String.fromCharCode(60,47,83,67,82,73,80,84,62));
</script><br />
<a href="http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1421822&afsid=1" target="_top"><img alt="Your Ad Here" border="0" height="60" src="http://files.adbrite.com/mb/images/adbrite-your-ad-here-banner.gif" style="background-color: #cccccc; border: medium none; margin: 0pt; padding: 0pt;" width="11" /></a></span><br />
<br />
<span style="font-size: 18px; font-weight: bold;">Introduction</span><br />
NewsGator’s primary software offering is a product called <a href="http://www.newsgator.com/products/social-sites-for-sharepoint-2010.aspx">Social Sites</a> which basically adds social networking aspects to Microsoft SharePoint. My role in this product is to create the iOS device apps that interact with the server. My app is pulling in a lot of data that an enterprise customer considers *very* sensitive so data protection is the first thing many CIOs ask about when considering Social Sites. This post is to layout both how iOS protects data on the device so our prospective clients have a better idea about how it works, along with some additional steps developers can take to further protect their data.<br />
Much of what I’ll discuss was covered in <a href="http://developer.apple.com/videos/wwdc/2010/">Session 209 at WWDC</a>, but since that information is under NDA, I’ll stick to information that’s available in the public domain (including <a href="http://anthonyvance.com/blog/forensics/iphone_encryption/">this post</a> about iPhone 3GS and <a href="http://anthonyvance.com/blog/forensics/ios4_data_protection/">this post</a> about iOS4). But if you have access to the WWDC videos, Session 209 is a great resource.<br />
<br />
<span style="font-size: 18px; font-weight: bold;">Data Encryption Starting with iPhone 3GS</span><br />
Social Sites uses Core Data with a SQLite store type for storage and persistence. When the app first runs, it creates a Social_Sites.sqlite database file in its sand boxed documents directory on the device file system.<br />
With the 3GS, any data written to the filesystem is encrypted using hardware encryption. By simply creating the Social_Sites.sqlite file on the file system, the data stored in it is already encrypted. This encryption also allows for the Social Sites data to be instantaneously unavailable when you use Remote Wipe. I say unavailable because the remote wipe doesn’t actually overwrite the encrypted data on the filesystem, but instead overwrites the hardware key used to encrypt/decrypt it. But still, the important thing is that the data on disk is encrypted.<br />
This type of data encryption is also used on the current iPads.<br />
<h2>Data Encryption on iOS 4</h2>The way hardware encryption works on iOS4 has been greatly improved. I can’t find any public document from Apple that explains the improvements in detail, but their <a href="http://support.apple.com/kb/HT4175">iOS 4: Understanding data protection</a> support page gives a hint with “Data protection enhances the built-in hardware encryption by protecting the hardware encryption keys with your passcode.” I’ll just say that hardware data encryption on the 3GS and iPad use a single hardware encryption key. The WWDC session goes into great detail about the under the hood improvements. The main takeaway for a CIO though is that the Social Sites sqlite datafile on iOS4 has stronger encryption than it did in the past.<br />
<h2>Further Protection – NSFileProtectionComplete</h2>In iOS4, Apple introduced data protection. It gives you the ability to encrypt the hardware keys used to encrypt your files and to erase those keys when the system is locked – leaving your file unreadable until the phone is unlocked and the keys are regenerated.<br />
This level of protection is not built in by default though. The user has to enable it (or an IT department can enable it and force users to have it on) and your code must set an attribute on your Core Data sqlite store as well.<br />
Steps for the user to enable data protection are outlined on the <a href="http://support.apple.com/kb/HT4175">iOS 4: Understanding data protection</a> support page. You need to have the passcode turned on since this is what the system will use to generate the encryption for the keys.<br />
As a developer, you need to set the NSFileProtection level of your sqlite store to NSFileProtectionComplete (by default it will be NSFileProtectionNone). You can do this right after you instantiate your persistent store coordinator:<br />
<br />
<code> </code><br />
<code> </code><br />
<code> </code><br />
<pre>- (<span style="color: #7c22ab;">NSPersistentStoreCoordinator</span> *)persistentStoreCoordinator {
<span style="color: black;"> </span><span style="color: #cc00a2;">if</span><span style="color: black;"> (</span>persistentStoreCoordinator<span style="color: black;"> != </span><span style="color: #cc00a2;">nil</span><span style="color: black;">) {</span>
<span style="color: black;"> </span><span style="color: #cc00a2;">return</span><span style="color: black;"> </span>persistentStoreCoordinator<span style="color: black;">;</span>
}
<span style="color: black; font-family: monospace;"><span style="font-size: medium;"> </span></span><span style="color: #7c22ab;"> NSString</span><span style="color: black;"> *storePath = [[</span><span style="color: #cc00a2;">self</span><span style="color: black;"> </span><span style="color: #245a5e;">applicationDocumentsDirectory</span><span style="color: black;">] </span>stringByAppendingPathComponent<span style="color: black;">: </span><span style="color: #e20300;">@"Social_Sites.sqlite"</span><span style="color: black;">];</span>
<span style="color: #7c22ab;">NSURL</span> *storeUrl = [<span style="color: #7c22ab;">NSURL</span> <span style="color: #470083;">fileURLWithPath</span>:storePath ];
<span style="color: #7c22ab;">NSError</span> *error = <span style="color: #cc00a2;">nil</span>;
<span style="color: black;"> </span><span style="color: #3f8288;">persistentStoreCoordinator</span><span style="color: black;"> = [[</span><span style="color: #7c22ab;">NSPersistentStoreCoordinator</span><span style="color: black;"> </span>alloc<span style="color: black;">] </span>initWithManagedObjectModel<span style="color: black;">: [</span><span style="color: #cc00a2;">self</span><span style="color: black;"> </span>managedObjectModel<span style="color: black;">]];</span>
<span style="color: black;"> </span><span style="color: #cc00a2;">if</span><span style="color: black;"> (![</span><span style="color: #3f8288;">persistentStoreCoordinator</span><span style="color: black;"> </span>addPersistentStoreWithType<span style="color: black;">:</span><span style="color: #7c22ab;">NSSQLiteStoreType</span><span style="color: black;"> </span>configuration<span style="color: black;">:</span><span style="color: #cc00a2;">nil</span><span style="color: black;"> </span>URL<span style="color: black;">:storeUrl </span>options<span style="color: black;">:</span><span style="color: #cc00a2;">nil</span><span style="color: black;"> </span>error<span style="color: black;">:&error]) {</span>
<span style="color: black;"> </span>// Handle error
}
<span style="color: #245a5e;"><span style="color: black;"> </span><span style="color: #cc00a2;">if</span><span style="color: black;">(</span>RSRunningOnOS4OrBetter<span style="color: black;">())</span></span>
{
<span style="color: black;"> </span><span style="color: black;"> </span>NSDictionary<span style="color: black;"> *fileAttributes = [</span>NSDictionary<span style="color: black;"> </span><span style="color: #470083;">dictionaryWithObject</span><span style="color: black;">:</span>NSFileProtectionComplete<span style="color: black;"> </span><span style="color: #470083;">forKey</span><span style="color: black;">:</span>NSFileProtectionKey<span style="color: black;">];</span>
<span style="color: #cc00a2;"><span style="color: black;"> </span></span> <span style="color: #cc00a2;">if</span> (![[<span style="color: #7c22ab;">NSFileManager</span> <span style="color: #470083;">defaultManager</span>] <span style="color: #470083;">setAttributes</span>:fileAttributes <span style="color: #470083;">ofItemAtPath</span>:storePath <span style="color: #470083;">error</span>:&error]) {
<span style="color: black;"> </span><span style="color: black;"> </span><span style="color: black;"> </span>// Handle error
}
}
<span style="color: black;"> </span><span style="color: #cc00a2;">return</span><span style="color: black;"> </span>persistentStoreCoordinator<span style="color: black;">;</span>
}
<span style="color: #cc00a2;">BOOL</span> RSRunningOnOS4OrBetter(<span style="color: #cc00a2;">void</span>) {
<span style="color: #cc00a2;"><span style="color: black;"> </span>static</span> <span style="color: #cc00a2;">BOOL</span> didCheckIfOnOS4 = <span style="color: #cc00a2;">NO</span>;
<span style="color: #cc00a2;"><span style="color: black;"> </span>static</span> <span style="color: #cc00a2;">BOOL</span> runningOnOS4OrBetter = <span style="color: #cc00a2;">NO</span>;
<span style="color: #cc00a2;"><span style="color: black;"> </span>if</span> (!didCheckIfOnOS4) {
<span style="color: black;"> </span><span style="color: black;"> </span>NSString<span style="color: black;"> *systemVersion = [</span>UIDevice<span style="color: black;"> </span><span style="color: #470083;">currentDevice</span><span style="color: black;">].</span>systemVersion<span style="color: black;">;</span>
<span style="color: #7c22ab;"><span style="color: black;"> </span></span> <span style="color: #7c22ab;">NSInteger</span> majorSystemVersion = <span style="color: #3d00db;">3</span>;
<span style="color: #cc00a2;"><span style="color: black;"> </span></span> <span style="color: #cc00a2;">if</span> (systemVersion != <span style="color: #cc00a2;">nil</span> && [systemVersion <span style="color: #470083;">length</span>] > <span style="color: #3d00db;">0</span>) { <span style="color: #008b00;">//Can't imagine it would be empty, but.</span>
<span style="color: #7c22ab;"><span style="color: black;"> </span></span> <span style="color: #7c22ab;">NSString</span> *firstCharacter = [systemVersion <span style="color: #470083;">substringToIndex</span>:<span style="color: #3d00db;">1</span>];
majorSystemVersion = [firstCharacter <span style="color: #470083;">integerValue</span>];<span style="white-space: pre;"> </span>
}
runningOnOS4OrBetter = (majorSystemVersion >= <span style="color: #3d00db;">4</span>);
didCheckIfOnOS4 = <span style="color: #cc00a2;">YES</span>;
}
<span style="color: #cc00a2;"><span style="color: black;"> </span>return</span> runningOnOS4OrBetter;
}</pre><span style="font-size: 12px; font-weight: bold;">Considerations</span><br />
If your application needs your Core Data store in any background processing, then you cannot use data protection. Any attempt to access files that are NSFileProtectionComplete will cause an exception.<br />
There are application delegates applicationProtectedDataWillBecomeUnavailable and applicationProtectedDataDidBecomeAvailable as well as notifications UIApplicationProtectedDataWillBecomeUnavailable and UIApplicationProtectedDataWillBecomeAvailable that you can use to determine what state your protected data is in.<br />
You could then in theory keep unprotected data in memory in your background processing then write it into your Core Data store when protected data becomes available again.<br />
You can find more information in the <a href="http://developer.apple.com/iphone/library/documentation/iphone/conceptual/iphoneosprogrammingguide/StandardBehaviors/StandardBehaviors.html">iPhone Application Programming Guide</a>.<br />
<br />
<span style="font-size: 24px; font-weight: bold;">Conclusions</span><br />
My answer to any CIO asking would be to ensure any device using Social Sites be a 3GS, an iPad or an iPhone 4. I would also encourage enforcing passcode and data protection for any device running iOS4. These steps ensure that the SQLite data store for Social Sites is hardware encrypted with remote wipe capabilities and further protected with iOS4 and data protection.<br />
UPDATE:<br />
Here’s the <a href="http://support.apple.com/kb/DL851">link to the iPhone Configuration Utility 3.0</a> which can be used to “create, maintain, encrypt, and install configuration profiles, track and install provisioning profiles and authorized applications, and capture device information including console logs.”<br />
<br />
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.facebook.com/pages/iPhone-Development-Center/176074875755527" show_faces="true" width="300"></fb:like>Tariqhttp://www.blogger.com/profile/12325091064660597676noreply@blogger.com0