<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Bushra Shahid&#039;s iOS stuff</title>
	<atom:link href="http://iosstuff.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://iosstuff.wordpress.com</link>
	<description>iOS development stuff i do and think about :)</description>
	<lastBuildDate>Wed, 22 Feb 2012 06:19:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='iosstuff.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Bushra Shahid&#039;s iOS stuff</title>
		<link>http://iosstuff.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://iosstuff.wordpress.com/osd.xml" title="Bushra Shahid&#039;s iOS stuff" />
	<atom:link rel='hub' href='http://iosstuff.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Using Apple&#8217;s App Review Process for Testing</title>
		<link>http://iosstuff.wordpress.com/2011/09/19/using-apples-app-review-process-for-testing/</link>
		<comments>http://iosstuff.wordpress.com/2011/09/19/using-apples-app-review-process-for-testing/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 05:02:04 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Idea]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[itunes-connect]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=191</guid>
		<description><![CDATA[Testing any piece of software is extremely important but if this software happens to be an iOS/Mac app, testing is crucial. Apple&#8217;s App Store Review Guidelines provide developers with some insight (some) on how they can avoid getting their app rejected. I say &#8216;some&#8217; because its a living document that constantly changes. Quotes from the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=191&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Testing any piece of software is extremely important but if this software happens to be an iOS/Mac app, testing is crucial. Apple&#8217;s App Store Review Guidelines provide developers with some insight (some) on how they can avoid getting their app rejected. I say &#8216;some&#8217; because its a living document that constantly changes. Quotes from the guidelines:</p>
<blockquote><p>This document represents our best efforts to share how we review apps submitted to the App Store, and we hope it is a helpful guide as you develop and submit your apps. It is a living document that will evolve as we are presented with new apps and situations, and we&#8217;ll update it periodically to reflect these changes.
</p></blockquote>
<p><span id="more-191"></span><br />
The developers may put their best efforts to provide Apple with a great application, the final and best judge of whether it should/would be approved is Apple and only Apple. This is especially applicable to apps that provide Location-based Services because a user&#8217;s location data is private and sensitive. Plus Apple&#8217;s testers are extremely thorough; if the app is using network, they would test it on 3G, wifi, and also without network; if it uses location they will test the app behavior while location services turned on and off; and so on. But, if an app is rejected despite all efforts of the developer, Apple provides detailed reasons of rejection with crash reports, screenshots, steps to replicate bugs, etc, in short everything that a developer needs to know to remove the behavior that caused rejection. Quoted from News and Announcements &gt; iOS on Apple&#8217;s developer portal:</p>
<blockquote><p>View Details Of Any Issues During App Review<br />
Mar 15, 2011<br />
You can now view details about any issues found during the review of your app from the new Resolution Center in iTunes Connect.<br />
If your app has been reviewed and needs further refining before it can be approved for the App Store, you will receive an email with a link to the iTunes Connect Resolution Center. The Resolution Center offers additional details, explanatory screenshots if applicable, and links to information on how to resolve any issues. You can also respond directly to the App Review Team from within the Resolution Center. All communications with the App Review Team will be visible to you and the Admin and Technical members of your team.</p></blockquote>
<p>Also the number of times same app can be submitted for review is unlimited, at least its not stated anywhere by Apple, nor has any developer complained as yet that Apple refused submission because the app was rejected and resubmitted too many times.</p>
<p>Knowing that Apple has a completely thorough and evolving method of reviewing App Store submissions, developers can use it for their benefit. Rather than putting too much time, effort and resources on extensive testing, developers can just develop their apps, do a little testing, submit for review, and let Apple do the dirty work. At the end of the day, they are the ones with absolute autonomy of whether something goes on the app store or not. Plus they give back everything developers need to mould their app according to Apple&#8217;s standards. Also if someone has already set a release date for their app, it would be good idea to submit a month or even two ahead of that date and provide the exact date when the app should go live after getting accepted using Release Control in iTunes Connect.</p>
<p>Bottom line, Apple&#8217;s Review process is the best testing process that an iOS/Mac app can go through; at least its the only best that matters.</p>
<p>P.S. I do not mean that one should submit an app that crashes every seconds and is full of bugs; developers should definitely take some time to test their applications. What I mean is one can do all the testing in the world and still get the app rejected; so instead of going overboard with it, just make sure the app works smoothly in normal conditions and let Apple do more extensive testing. </p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/general/'>General</a>, <a href='http://iosstuff.wordpress.com/category/idea/'>Idea</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/app/'>app</a>, <a href='http://iosstuff.wordpress.com/tag/apple/'>apple</a>, <a href='http://iosstuff.wordpress.com/tag/ipad/'>ipad</a>, <a href='http://iosstuff.wordpress.com/tag/iphone/'>iphone</a>, <a href='http://iosstuff.wordpress.com/tag/itunes-connect/'>itunes-connect</a>, <a href='http://iosstuff.wordpress.com/tag/mac/'>mac</a>, <a href='http://iosstuff.wordpress.com/tag/review-2/'>review</a>, <a href='http://iosstuff.wordpress.com/tag/testing/'>testing</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/191/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/191/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/191/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/191/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/191/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/191/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/191/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/191/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=191&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/09/19/using-apples-app-review-process-for-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>
	</item>
		<item>
		<title>Bring Users Back to your Application after they End the Call</title>
		<link>http://iosstuff.wordpress.com/2011/09/06/bring-users-back-to-your-application-after-they-end-the-call/</link>
		<comments>http://iosstuff.wordpress.com/2011/09/06/bring-users-back-to-your-application-after-they-end-the-call/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 08:21:50 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[after]]></category>
		<category><![CDATA[automatically]]></category>
		<category><![CDATA[back]]></category>
		<category><![CDATA[back to app after call]]></category>
		<category><![CDATA[call]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[open app after call]]></category>
		<category><![CDATA[phone]]></category>
		<category><![CDATA[return]]></category>
		<category><![CDATA[return to app after call]]></category>
		<category><![CDATA[sdk]]></category>
		<category><![CDATA[tel:]]></category>
		<category><![CDATA[uiwebview]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=186</guid>
		<description><![CDATA[Often times, developers want to allow their users to place calls from inside their applications. Although, Apple has provided a pretty neat function openURL: for doing that, but it has one disadvantage&#8230;rather than bringing the users back to the application, it takes the users to the default Phone application after they end the call. It [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=186&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Often times, developers want to allow their users to place calls from inside their applications. Although, Apple has provided a pretty neat function <span style="color:#cc0000;">openURL:</span> for doing that, but it has one disadvantage&#8230;rather than bringing the users back to the application, it takes the users to the default Phone application after they end the call. It can be frustrating to both the developers and the users; developers want to give uninterrupted use of their applications whereas users hate to have to close the Phone app and go back to what they were doing. If you are one of the afore mentioned developers, you are reading just the post. In this small pots, Im showing a way around this&#8230;as always, totally acceptable by Apple, no private APIs or hacks that may get your app rejected.</p>
<p><span id="more-186"></span></p>
<p>No magic here, just a little observation; if you have ever made a call from Safari, you would have noticed that ending the call takes you back to Safari. Like me, you must have believed that Apple has added this custom behavior to Safari which is not accessible to us, bla bla bla&#8230;..actually thats not the case. This is UIWebView magic and if you use UIWebView to make calls instead of <span style="color:#cc0000;">openURL:</span>, you would get the same behavior. Lets see how to do that.</p>
<h2>Using UIWebView to Place Calls</h2>
<p>Simply, open your tel URL in a UIWebView. Like this</p>
<pre><code><span style="color:#cc0000;">UIWebView *callWebview = [[UIWebView alloc] init];
NSURL *telURL = [NSURL URLWithString:@"tel:<em>number to call</em>"];
[callWebview loadRequest:[NSURLRequest requestWithURL:telURL]];</pre>
<p></code></span></p>
<p>See, you dont even have to add the webview to your UI. Isn't this awesome?? Whats more awesome is, it displays an alert for confirmation before actually placing the call <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Feel free to leave a comment and wander around on my blog to find out more interesting stuff. You can also <a href="feed://iosstuff.wordpress.com/feed/" title="feed">follow</a> me here or on twitter (<a href="http://twitter.com/#!/xs2bush" title="@xs2bush">@xs2bush</a>) to stay updated. Happy Coding <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Update: The second line of code was missing a semi colon, thanks Ken for pointing that out. Also the UIWebView object was accesses using wrong variable name. All is correct now! I apologize for any inconvenience that it has might caused anyone <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I have tested it on my iPhone and it works perfectly.</p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/tutorial/'>Tutorial</a>, <a href='http://iosstuff.wordpress.com/category/user-experience/'>User Experience</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/after/'>after</a>, <a href='http://iosstuff.wordpress.com/tag/automatically/'>automatically</a>, <a href='http://iosstuff.wordpress.com/tag/back/'>back</a>, <a href='http://iosstuff.wordpress.com/tag/back-to-app-after-call/'>back to app after call</a>, <a href='http://iosstuff.wordpress.com/tag/call/'>call</a>, <a href='http://iosstuff.wordpress.com/tag/ios-2/'>ios</a>, <a href='http://iosstuff.wordpress.com/tag/iphone/'>iphone</a>, <a href='http://iosstuff.wordpress.com/tag/objective-c/'>objective-c</a>, <a href='http://iosstuff.wordpress.com/tag/open-app-after-call/'>open app after call</a>, <a href='http://iosstuff.wordpress.com/tag/phone/'>phone</a>, <a href='http://iosstuff.wordpress.com/tag/return/'>return</a>, <a href='http://iosstuff.wordpress.com/tag/return-to-app-after-call/'>return to app after call</a>, <a href='http://iosstuff.wordpress.com/tag/sdk/'>sdk</a>, <a href='http://iosstuff.wordpress.com/tag/tel/'>tel:</a>, <a href='http://iosstuff.wordpress.com/tag/uiwebview/'>uiwebview</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/186/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/186/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=186&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/09/06/bring-users-back-to-your-application-after-they-end-the-call/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>
	</item>
		<item>
		<title>Accessing iPhone Call History</title>
		<link>http://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/</link>
		<comments>http://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 09:23:17 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[call]]></category>
		<category><![CDATA[call_history.db]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[log]]></category>
		<category><![CDATA[NSDirectoryEnumerator]]></category>
		<category><![CDATA[NSFileManager]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[sqlite]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=161</guid>
		<description><![CDATA[Although there is no API in the SDK to access iPhone&#8217;s Call History, there is a read-only SQLite database that gives access to the call history. In this tutorial, we shall learn what is the name of this database; where is it stored; what is its schema; and finally how can we access it? Call [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=161&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Although there is no API in the SDK to access iPhone&#8217;s Call History, there is a read-only SQLite database that gives access to the call history. In this tutorial, we shall learn what is the name of this database; where is it stored; what is its schema; and finally how can we access it?</p>
<p><span id="more-161"></span></p>
<h2>Call History Database &#8211; Path, and Schema</h2>
<p>The iPhone call history is stored in &#8220;call_history.db&#8221; which is located at the following path:</p>
<pre><code><span style="color:#cc0000;"><em>/private/var/root/Library/CallHistory/call_history.db</em></span></code></pre>
<p><em></em>There are other important databases on the iPhone, some of which are accessible and some are not. We can find that out using the following piece of code. This basically enumerates the system folder and subfolders and finds databases that are readable:</p>
<pre><code><span style="color:#cc0000;">NSFileManager *fileManager = [NSFileManager defaultManager];
NSDirectoryEnumerator *dirnum = [[NSFileManager defaultManager] enumeratorAtPath: @"/private/"];
NSString *nextItem = [NSString string];
while( (nextItem = [dirnum nextObject])) {
    if ([[nextItem pathExtension] isEqualToString: @"db"] ||
        [[nextItem pathExtension] isEqualToString: @"sqlitedb"]) {
        if ([fileManager isReadableFileAtPath:nextItem]) {
            NSLog(@"%@", nextItem);
        }
    }
}</span></code></pre>
<p>I got the following results:</p>
<p><strong>var/db/launchd.db</strong><br />
<strong>var/mobile/Library/AddressBook/AddressBook.sqlitedb</strong><br />
<strong>var/mobile/Library/AddressBook/AddressBookImages.sqlitedb</strong><br />
<strong>var/wireless/Library/CallHistory/call_history.db</strong></p>
<p>Feel free to share yours <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So now we have the database path and we can easily read the values stored in it, but to know what value is what we need to know the schema. Here is a snippet to find that out:</p>
<pre><code><span style="color:#cc0000;">NSString *callHisoryDatabasePath = @"/private/var/wireless/Library/CallHistory/call_history.db";
BOOL callHistoryFileExist = FALSE;
callHistoryFileExist = [fileManager fileExistsAtPath:callHisoryDatabasePath];
[fileManager release];

if(callHistoryFileExist) {
    if ([fileManager isReadableFileAtPath:callHisoryDatabasePath]) {
        sqlite3 *database;
        if(sqlite3_open([callHisoryDatabasePath UTF8String], &amp;database) == SQLITE_OK) {

            //Getting table names and schema
            sqlite3_stmt *compiledStatement;
            NSString *sqlStatement = [NSString stringWithString:
                                    @"SELECT * FROM sqlite_master WHERE type='table';"];
            int errorCode = sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1,
                                                 &amp;compiledStatement, NULL);

            if( errorCode == SQLITE_OK) {
                int count = 1;
                while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                    // Read the data from the result row
                    int numberOfColumns = sqlite3_column_count(compiledStatement);
                    NSString *data;
                    NSString *columnName;
                    for (int i = 0; i &lt; numberOfColumns; i++) {
                        columnName = [[NSString alloc] initWithUTF8String:
                                     (char *)sqlite3_column_name(compiledStatement, i)];
                        data = [[NSString alloc] initWithUTF8String:
                                 (char *)sqlite3_column_text(compiledStatement, i)];

                        NSLog(@"%@ : %@", columnName, data);

                        [columnName release];
                        [data release];
                    }
                    count++;
                }
            }
            else {
                NSLog(@"Failed to retrieve table");
                NSLog(@"Error Code: %d", errorCode);
            }
            sqlite3_finalize(compiledStatement);
        }
    }
}</span></code></pre>
<p>You will get something like this:</p>
<p><strong>type : table</strong><br />
<strong> name : _SqliteDatabaseProperties</strong><br />
<strong> tbl_name : _SqliteDatabaseProperties</strong><br />
<strong> rootpage : 2</strong><br />
<strong> sql : CREATE TABLE _SqliteDatabaseProperties (key TEXT, value TEXT, UNIQUE(key))</strong></p>
<p><strong> type : table</strong><br />
<strong> name : call</strong><br />
<strong> tbl_name : call</strong><br />
<strong> rootpage : 4</strong><br />
<strong> sql : CREATE TABLE call (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, address TEXT, date INTEGER, duration INTEGER, flags INTEGER, id INTEGER, name TEXT, country_code TEXT)</strong></p>
<p><strong> type : table</strong><br />
<strong> name : sqlite_sequence</strong><br />
<strong> tbl_name : sqlite_sequence</strong><br />
<strong> rootpage : 5</strong><br />
<strong> sql : CREATE TABLE sqlite_sequence(name,seq)</strong></p>
<p><strong> type : table</strong><br />
<strong> name : data</strong><br />
<strong> tbl_name : data</strong><br />
<strong> rootpage : 6</strong><br />
<strong> sql : CREATE TABLE data (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, pdp_ip INTEGER, bytes_rcvd REAL, bytes_sent REAL, bytes_last_rcvd REAL, bytes_last_sent REAL, bytes_lifetime_rcvd REAL, bytes_lifetime_sent REAL)</strong></p>
<p>More info on other iphone databases can be found on this link:</p>
<p><a href="http://itunes.apple.com/us/app/callog/id327883585?mt=8">http://damon.durandfamily.org/archives/000487.html</a></p>
<h2>Accessing the Call History</h2>
<p>Now that we know the call history db path and schema, we can see that we are interested in the &#8220;call&#8221; table. Thanks to the above link, we know what exactly is stored in this table:</p>
<p><strong>ROWID (INTEGER PRIMARY KEY AUTOINCREMENT) :</strong>   <em>Auto-incrementing field/counter</em><br />
<em></em><strong>address (TEXT) :</strong>   <em>International-formatted foreign address </em><br />
<em></em><strong>date (INTEGER) :</strong>  <em>OSX-epoch based datetime, convertable via date -r</em><br />
<em></em><strong>duration (INTEGER) :</strong>  <em>Length of call in seconds rounded to next minute, 0 = missed call</em><br />
<em></em><strong>flags (INTEGER) :</strong>  <em>Flags controlling the type of record; 5 &#8211; Outgoing call | 4 &#8211; Incoming call</em><br />
<em></em><strong>id (INTEGER) :</strong>  <em>AddressBook ID for outgoing calls selected from AddressBook, otherwise -1</em></p>
<p>Now we should write some code to access that. The following code accesses the &#8220;call&#8221; table and stores the retrieved values in an array of dictionaries. You could write your own class and use an array of objects of that class:</p>
<pre><code><span style="color:#cc0000;">NSString *callHisoryDatabasePath = @"/private/var/wireless/Library/CallHistory/call_history.db";
BOOL callHistoryFileExist = FALSE;
callHistoryFileExist = [fileManager fileExistsAtPath:callHisoryDatabasePath];
[fileManager release];
NSMutableArray *callHistory = [[NSMutableArray alloc] init];

if(callHistoryFileExist) {
    if ([fileManager isReadableFileAtPath:callHisoryDatabasePath]) {
        sqlite3 *database;
        if(sqlite3_open([callHisoryDatabasePath UTF8String], &amp;database) == SQLITE_OK) {
            sqlite3_stmt *compiledStatement;
            NSString *sqlStatement = [NSString stringWithString:@"SELECT * FROM call;"];

            int errorCode = sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1,
                                                &amp;compiledStatement, NULL);
            if( errorCode == SQLITE_OK) {
                int count = 1;

                while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                    // Read the data from the result row
                    NSMutableDictionary *callHistoryItem = [[NSMutableDictionary alloc] init];
                    int numberOfColumns = sqlite3_column_count(compiledStatement);
                    NSString *data;
                    NSString *columnName;

                    for (int i = 0; i &lt; numberOfColumns; i++) {
                        columnName = [[NSString alloc] initWithUTF8String:
                                    (char *)sqlite3_column_name(compiledStatement, i)];
                        data = [[NSString alloc] initWithUTF8String:
                                (char *)sqlite3_column_text(compiledStatement, i)];

                        [callHistoryItem setObject:data forKey:columnName];

                        [columnName release];
                        [data release];
                    }
                    [callHistory addObject:callHistoryItem];
                    [callHistoryItem release];
                    count++;
                }
            }
            else {
                NSLog(@"Failed to retrieve table");
                NSLog(@"Error Code: %d", errorCode);
            }
            sqlite3_finalize(compiledStatement);
        }
    }
}</span></code></pre>
<p>If you want to show date as a real date not number of seconds since epoch use this if-statement:</p>
<pre><code><span style="color:#cc0000;">if (![columnName isEqualToString:@"date"]) {
    [callHistoryItem setObject:data forKey:columnName];
}
else {

    NSDate *callDate = [NSDate dateWithTimeIntervalSince1970:[data intValue]];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterFullStyle];
    [dateFormatter setTimeStyle:NSDateFormatterFullStyle];
    [dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];

[callHistoryItem setObject:[dateFormatter stringFromDate:callDate] forKey:columnName];

}</span></code></pre>
<p>Other conditions can be added to check the &#8216;flag&#8217; and determining whether the call is incoming or outgoing.</p>
<p>Dont be afraid of using this in an application for the app store. There is already <a href="http://itunes.apple.com/us/app/callog/id327883585?mt=8">an app on iTunes that accesses call history</a>.</p>
<p>Note: I found values other than 4 and 5 for flags, like 20,21. I dont know what they mean yet. Ill update as soon as I do. Meanwhile, you guys share what different values you get with us and also if you find out what they mean.</p>
<p>Happy Coding <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/tutorial/'>Tutorial</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/call/'>call</a>, <a href='http://iosstuff.wordpress.com/tag/call_history-db/'>call_history.db</a>, <a href='http://iosstuff.wordpress.com/tag/history/'>history</a>, <a href='http://iosstuff.wordpress.com/tag/ios-2/'>ios</a>, <a href='http://iosstuff.wordpress.com/tag/iphone/'>iphone</a>, <a href='http://iosstuff.wordpress.com/tag/log/'>log</a>, <a href='http://iosstuff.wordpress.com/tag/nsdirectoryenumerator/'>NSDirectoryEnumerator</a>, <a href='http://iosstuff.wordpress.com/tag/nsfilemanager/'>NSFileManager</a>, <a href='http://iosstuff.wordpress.com/tag/objective-c/'>objective-c</a>, <a href='http://iosstuff.wordpress.com/tag/sqlite/'>sqlite</a>, <a href='http://iosstuff.wordpress.com/tag/xcode/'>xcode</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/161/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/161/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/161/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/161/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/161/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/161/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/161/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/161/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=161&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/feed/</wfw:commentRss>
		<slash:comments>50</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>
	</item>
		<item>
		<title>Creating &#8216;Pulse&#8217; style scrolling &#8211; Horizontally scrolling UITableView as a subview of UITableViewCell</title>
		<link>http://iosstuff.wordpress.com/2011/06/29/creating-pulse-style-scrolling-horizontally-scrolling-uitableview-as-a-subview-of-uitableviewcell/</link>
		<comments>http://iosstuff.wordpress.com/2011/06/29/creating-pulse-style-scrolling-horizontally-scrolling-uitableview-as-a-subview-of-uitableviewcell/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 09:06:41 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[cell]]></category>
		<category><![CDATA[cgaffinetransform]]></category>
		<category><![CDATA[cgaffinetransformmakerotation]]></category>
		<category><![CDATA[custom]]></category>
		<category><![CDATA[horizontal]]></category>
		<category><![CDATA[horizontal scroll]]></category>
		<category><![CDATA[horizontal tables]]></category>
		<category><![CDATA[horizontal tableviews]]></category>
		<category><![CDATA[horizontal tableviews like pulse]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[m_pi_2]]></category>
		<category><![CDATA[pulse]]></category>
		<category><![CDATA[rotate]]></category>
		<category><![CDATA[rotated tables]]></category>
		<category><![CDATA[rotation]]></category>
		<category><![CDATA[scrolling]]></category>
		<category><![CDATA[sdk]]></category>
		<category><![CDATA[subview]]></category>
		<category><![CDATA[table]]></category>
		<category><![CDATA[tableview]]></category>
		<category><![CDATA[tableviewcell]]></category>
		<category><![CDATA[transform]]></category>
		<category><![CDATA[uitableviewcell]]></category>
		<category><![CDATA[uitableviewcontroller]]></category>
		<category><![CDATA[uitableviewdatasource]]></category>
		<category><![CDATA[uitableviewdelegate]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=90</guid>
		<description><![CDATA[&#8216;Pulse&#8217; is a free news reading application for iPhone, iPad, and Android by Alphonso Labs Inc. I was introduced to Pulse through an iTunes U lecture from Stanford University &#8220;10 Hacks to go from Idea to #1 App&#8221;. In that lecture, the developers have mentioned that they have used horizontal UITableViews to create the Interface. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=90&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.alphonsolabs.com/products">&#8216;Pulse&#8217; is a free news reading application for iPhone, iPad, and Android by Alphonso Labs Inc.</a> I was introduced to Pulse through an iTunes U lecture from Stanford University &#8220;10 Hacks to go from Idea to #1 App&#8221;. In that lecture, the developers have mentioned that they have used horizontal UITableViews to create the Interface. Intrigued as I was, I had to try it myself and you should also.</p>
<p><span id="more-90"></span><br />
Pulse has a unique UI that is as useful as it is pretty:</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/mzl-dbzsauiu-320x480-75.jpg"><img class="alignnone size-full wp-image-117" title="Pulse screenshot" src="http://iosstuff.files.wordpress.com/2011/06/mzl-dbzsauiu-320x480-75.jpg?w=590" alt=""   /></a></p>
<p>Each row contain feed from a single source and is horizontally scrollable. The visual representation is enough to get the gist of overall news and read only the stories that seem interesting or important. While this is a unique and efficient news reading application for the users, its also appealing to the developers (at least it was to me.)</p>
<p>So, here is a tutorial for creating the same interface (scree on the left):</p>
<h1> Things We Need</h1>
<p>1. A UITableView whose cells have other UITableViews as subviews. You might find <a title="Adding a UITableView as a subview of UITableViewCell using Interface Builder" href="http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/">this tutorial</a> helpful.</p>
<p>2. A bunch of images.</p>
<p>3. A taste for uniqueness. Most Important!</p>
<h1>Lets Start</h1>
<p>What we&#8217;re going to do is rotate our tableview that is the subview by -90 degrees. Then we are going to add images to each of its cells and rotate those images by 90 degrees.</p>
<h3>Adjusting Sizes in IB</h3>
<p>To start with, lets adjust the sizes a little bit. Open TableViewCell.xib (our UITableViewCell subclass from the <a title="Adding a UITableView as a subview of UITableViewCell using Interface Builder" href="http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/">above mentioned tutorial</a>) and change the sizes as following:</p>
<p>1. Make the cell&#8217;s &#8216;View&#8217; 320&#215;220 for iPhone or 768&#215;220 for iPad.</p>
<p>2. Make the UITableView 220&#215;768. (Yes, the width and height is opposite to that of the cell because we&#8217;re going to rotate it.)</p>
<h3>Adding and Initializing Required Properties</h3>
<p>In our UITableViewController subclass, we need an array of arrays. Each of its object (i.e. an array) is going to contain a collection of objects that we want to be displayed in our horizontal tableview, in this case NSString objects having names of images. Lets declare those in our header file:</p>
<p><code>
<pre>
<span style="color:#888888;">#import &lt;UIKit/UIKit.h&gt;</span>

<span style="color:#888888;">@class TableViewCell;</span>

<span style="color:#888888;">@interface TableViewController : UIViewController &lt;UITableViewDataSource, UITableViewDelegate&gt; {</span>
<span style="color:#888888;">      UITableView *tableView;</span>
<span style="color:#888888;">      TableViewCell *tableViewCell;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">@property (nonatomic, retain) IBOutlet UITableView *tableView;</span>
<span style="color:#888888;">@property (nonatomic, retain) IBOutlet TableViewCell *tableViewCell;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *titlesArray;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *peopleArray;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *thingsArray;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *fruitsArray;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *arrays;</span>

<span style="color:#888888;">@end</span></pre>
<p></code></p>
<p>and initialize in the implementation file:</p>
<p><code>
<pre>
<span style="color:#888888;">- (void)viewDidLoad </span><span class="Apple-style-span" style="color:#888888;">{</span>
<span style="color:#888888;">      [super viewDidLoad];</span>

<span style="color:#888888;">      titlesArray = [[NSArray alloc] initWithObjects:@"People", @"Things", @"Fruits", nil];</span>
<span style="color:#888888;">      peopleArray = [[NSArray alloc] initWithObjects:@"Gardener.png", @"Plumber.png",
                    @"BusinessWoman.png", @"BusinessMan.png", @"Chef.png", @"Doctor.png", nil];</span>
<span style="color:#888888;">      thingsArray = [[NSArray alloc] initWithObjects:@"StopWatch.png", @"TrashCan.png",
                    @"Key.png", @"Telephone.png", @"ChalkBoard.png", @"Bucket.png", nil];</span>
<span style="color:#888888;">      fruitsArray = [[NSArray alloc] initWithObjects:@"Pineapple.png", @"Orange.png",
                    @"Apple.png", nil];</span>

<span style="color:#888888;">      arrays = [[NSArray alloc] initWithObjects:peopleArray, thingsArray, fruitsArray, nil];</span>
<span style="color:#888888;">}</span>
</pre>
<p></code><br />
In our UITableViewCell subclass, we need an array to hold the content that is going to be displayed in its tableview. Lets declare that in its header:</p>
<p><code>
<pre>
<span style="color:#888888;">#import &lt;UIKit/UIKit.h&gt;</span>

<span style="color:#888888;">@interface TableViewCell : UITableViewCell &lt;UITableViewDataSource, UITableViewDelegate&gt; {</span>
<span style="color:#888888;">      UITableView *horizontalTableView;</span>
<span style="color:#888888;">      NSArray *contentArray;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">@property (nonatomic, retain) IBOutlet UITableView *horizontalTableView;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *contentArray;</span>

<span style="color:#888888;">@end</span>
</pre>
<p></code></p>
<p>It will later be initialized in tableView:cellForRowAtIndexPath in the UITableViewController subclass.</p>
<h3>Altering UITableViewDelegate and DataSource</h3>
<p>We implemented UITableViewDelegate and DataSource for both our UITableViewController subclass and UITableViewCell subclass <a title="Adding a UITableView as a subview of UITableViewCell using Interface Builder" href="http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/">earlier</a>. Now, we just need to change them a little bit.</p>
<p>In UITableViewController subclass, the datasource method tableView:cellForRowAtIndexPath: will be (Please also have a look at the second update):</p>
<p><code>
<pre>
<span style="color:#888888;">- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{</span>
<span style="color:#888888;">      static NSString *CellIdentifier = @"Cell";</span>
<span style="color:#888888;">      TableViewCell *cell = (TableViewCell*)[self.tableView
                         dequeueReusableCellWithIdentifier:CellIdentifier];</span>

<span style="color:#888888;">      if (cell == nil) {</span>
<span style="color:#888888;">           [[NSBundle mainBundle] loadNibNamed:@"TableViewCell" owner:self options:nil];</span>

<span style="color:#888888;">           CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);</span>
<span style="color:#888888;">           tableViewCell.horizontalTableView.transform = rotateTable;</span>
<span style="color:#888888;">           tableViewCell.horizontalTableView.frame = CGRectMake(0, 0,
                         tableViewCell.horizontalTableView.frame.size.width,
                         tableViewCell.horizontalTableView.frame.size.height);</span>

<span style="color:#888888;">           tableViewCell.contentArray = [arrays objectAtIndex:indexPath.section];</span>
<span style="color:#888888;">           tableViewCell.horizontalTableView.allowsSelection = NO;</span>

<span style="color:#888888;">           cell = tableViewCell;</span>
<span style="color:#888888;">           self.tableViewCell = nil;</span>
<span style="color:#888888;">      }</span>

<span style="color:#888888;">      return cell;</span>
<span style="color:#888888;">}</span>
</pre>
<p></code></p>
<p>Note: horizontalTableView is the subview of TableViewCell. In the preparatory tutorial it was named tableViewInsideCell.</p>
<p>Since we are separating the content through sections rather than rows, there are going to be more than one sections each having one row:</p>
<p><code>
<pre>
<span style="color:#888888;">- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {</span>
<span style="color:#888888;">      // Return the number of sections.</span>
<span style="color:#888888;">      return [arrays count];</span>

<span style="color:#888888;">} </span>
<span style="color:#888888;">- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {</span>
<span style="color:#888888;">      return 1;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {</span>
<span style="color:#888888;">      return [titlesArray objectAtIndex:section];</span>
<span style="color:#888888;">}</span>
</pre>
<p></code></p>
<p>Also change the height of each row to 220:</p>
<p><code>
<pre>
<span style="color:#888888;">- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {</span>
<span style="color:#888888;">      return 220;</span>
<span style="color:#888888;">}</span>
</pre>
<p></code><br />
In UITableViewCell subclass, tableView:cellForRowAtIndexPath: will be:</p>
<p><code>
<pre>
<span style="color:#888888;">- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{</span>
<span style="color:#888888;">      static NSString *CellIdentifier = @"Cell";</span>
<span style="color:#888888;">      UITableViewCell *cell = [self.horizontalTableView
                           dequeueReusableCellWithIdentifier:CellIdentifier];</span>

<span style="color:#888888;">      if (cell == nil) {</span>
<span style="color:#888888;">           cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                              reuseIdentifier:CellIdentifier] autorelease];</span>
<span style="color:#888888;">      }</span>

<span style="color:#888888;">      //Since we are reusing the cells, old image view needs to be removed form the cell</span>
<span style="color:#888888;">      for (UIImageView *view in cell.subviews) {</span>
<span style="color:#888888;">            [view removeFromSuperview];</span>
<span style="color:#888888;">      }</span>

<span style="color:#888888;">      UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];</span>
<span style="color:#888888;">      imageView.image = [UIImage imageNamed:[contentArray objectAtIndex:indexPath.row]];</span>

<span style="color:#888888;">      //Use UIContentModeScaleAspectFit or other depending upon the size of your images,
                    mine were small but not proportional so...    </span>
<span style="color:#888888;">      imageView.contentMode = UIViewContentModeCenter;</span>
<span style="color:#888888;">      CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);</span>
<span style="color:#888888;">      imageView.transform = rotateImage;</span>

<span style="color:#888888;">      [cell addSubview:imageView];</span>
<span style="color:#888888;">      [imageView release];</span>

<span style="color:#888888;">      return cell;</span>
<span style="color:#888888;">}</span>
</pre>
<p></code></p>
<p>Adjust the row height here also:</p>
<p><code>
<pre>
<span style="color:#888888;">- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {</span>
<span style="color:#888888;">      return 220;</span>
<span style="color:#888888;">}</span>
</pre>
<p></code></p>
<p>and done!</p>
<p>Here is what the result would look like:</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/pulse-style-scrolling.png"><img class="alignnone size-full wp-image-127" title="Pulse-style scrolling" src="http://iosstuff.files.wordpress.com/2011/06/pulse-style-scrolling.png?w=590" alt=""   /></a></p>
<p>Again, its raw, certainly not as pretty as Pulse, but it can be (rather should be) refined before using in an actual application. If it helped, you&#8217;re welcome <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Any improvements or suggestions are most welcome in the comments sections. Do subscribe for more unique stuff.</p>
<h4>Update</h4>
<p>Borut pointed out that our custom cells with UITableView inside them are not being reused. If we study the code carefully, we will find out that we are not assigning any reuseIdentifier because we are not using the default -initWithStyle:reuseIdentifier method for creating cells. The reuseIdentifier property of UITableViewCell is readonly , we cannot set it. A workaround is to create a getter method in our UITableViewCell subclass for the reuseIdentifier and use the same string being used to dequeue the reusable cells. In our case, this should do:</p>
<p><code>
<pre>
<span style="color:#888888;">- (NSString *) reuseIdentifier {
    return @"Cell";
}</span>
</pre>
<p></code></p>
<p>Note that in this tutorial we are using @&#8221;Cell&#8221; for dequeuing cells in both UITableViewCell subclass and UITableViewController subclass. This needs to return the one we are using in the UITableViewCOntroller subclass because we want to reuse this cell there. </p>
<h4>Update 2</h4>
<p>Borut wanted to update the content dynamically and was having problems with the current version. Like I said earlier, this is a very limited implementation and can be improved. We improved it a little more. If you want to dynamically add remove content, change the &#8216;arrays&#8217; ivar type to NSMutableArray and update the array. Now we need to tell our two tableviews to reload, not one, but two tableviews. First call reload on the parent tableView after editing the array, example:</p>
<p><code>
<pre>
<span style="color:#888888;">[arrays removeLastObject];
[self.tableView reloadData];</span>
</pre>
<p></code></p>
<p>Next we change our cellForRowAtIndexPath of parent tableView to add a method call to reload the child tableView:</p>
<p><code>
<pre>
<span style="color:#888888;">-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    TableViewCell *cell = (TableViewCell*)[self.tableView
                          dequeueReusableCellWithIdentifier:CellIdentifier];
	if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"TableViewCell" owner:self options:nil];
        cell = tableViewCell;
		self.tableViewCell = nil;

    //changed the location of the closing bracket
    }   

    CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
    cell.horizontalTableView.transform = rotateTable;
    cell.horizontalTableView.frame = CGRectMake(0, 0, cell.horizontalTableView.frame.size.width,
                                     cell.horizontalTableView.frame.size.height);

    cell.contentArray = [arrays objectAtIndex:indexPath.section];

    //addition
    [cell reloadContent];
    cell.horizontalTableView.allowsSelection = YES;

    return cell;
}</span>
</pre>
<p></code></p>
<p>Now also add the reloadContent method to the UITableViewCell subclass:</p>
<p><code>
<pre>
<span style="color:#888888;">- (void)reloadContent {
    [self.horizontalTableView reloadData];
}</span>
</pre>
<p></code></p>
<h4>Update 3</h4>
<p>Thanks a lot for your appreciation. Since there were a lot of requests for code. I&#8217;ve uploaded it to dropbox. Here is the link:<br />
<a href="http://dl.dropbox.com/u/17653793/Pulse.zip">http://dl.dropbox.com/u/17653793/Pulse.zip</a></p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/tutorial/'>Tutorial</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/cell/'>cell</a>, <a href='http://iosstuff.wordpress.com/tag/cgaffinetransform/'>cgaffinetransform</a>, <a href='http://iosstuff.wordpress.com/tag/cgaffinetransformmakerotation/'>cgaffinetransformmakerotation</a>, <a href='http://iosstuff.wordpress.com/tag/custom/'>custom</a>, <a href='http://iosstuff.wordpress.com/tag/horizontal/'>horizontal</a>, <a href='http://iosstuff.wordpress.com/tag/horizontal-scroll/'>horizontal scroll</a>, <a href='http://iosstuff.wordpress.com/tag/horizontal-tables/'>horizontal tables</a>, <a href='http://iosstuff.wordpress.com/tag/horizontal-tableviews/'>horizontal tableviews</a>, <a href='http://iosstuff.wordpress.com/tag/horizontal-tableviews-like-pulse/'>horizontal tableviews like pulse</a>, <a href='http://iosstuff.wordpress.com/tag/ios-2/'>ios</a>, <a href='http://iosstuff.wordpress.com/tag/iphone/'>iphone</a>, <a href='http://iosstuff.wordpress.com/tag/m_pi_2/'>m_pi_2</a>, <a href='http://iosstuff.wordpress.com/tag/pulse/'>pulse</a>, <a href='http://iosstuff.wordpress.com/tag/rotate/'>rotate</a>, <a href='http://iosstuff.wordpress.com/tag/rotated-tables/'>rotated tables</a>, <a href='http://iosstuff.wordpress.com/tag/rotation/'>rotation</a>, <a href='http://iosstuff.wordpress.com/tag/scrolling/'>scrolling</a>, <a href='http://iosstuff.wordpress.com/tag/sdk/'>sdk</a>, <a href='http://iosstuff.wordpress.com/tag/subview/'>subview</a>, <a href='http://iosstuff.wordpress.com/tag/table/'>table</a>, <a href='http://iosstuff.wordpress.com/tag/tableview/'>tableview</a>, <a href='http://iosstuff.wordpress.com/tag/tableviewcell/'>tableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/transform/'>transform</a>, <a href='http://iosstuff.wordpress.com/tag/uitableviewcell/'>uitableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/uitableviewcontroller/'>uitableviewcontroller</a>, <a href='http://iosstuff.wordpress.com/tag/uitableviewdatasource/'>uitableviewdatasource</a>, <a href='http://iosstuff.wordpress.com/tag/uitableviewdelegate/'>uitableviewdelegate</a>, <a href='http://iosstuff.wordpress.com/tag/xcode/'>xcode</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/90/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/90/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/90/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/90/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/90/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/90/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/90/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/90/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=90&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/06/29/creating-pulse-style-scrolling-horizontally-scrolling-uitableview-as-a-subview-of-uitableviewcell/feed/</wfw:commentRss>
		<slash:comments>82</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/mzl-dbzsauiu-320x480-75.jpg" medium="image">
			<media:title type="html">Pulse screenshot</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/pulse-style-scrolling.png" medium="image">
			<media:title type="html">Pulse-style scrolling</media:title>
		</media:content>
	</item>
		<item>
		<title>Adding a UITableView as a subview of UITableViewCell using Interface Builder</title>
		<link>http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/</link>
		<comments>http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 08:42:41 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[cell]]></category>
		<category><![CDATA[custom tableview cell]]></category>
		<category><![CDATA[custom uitableviewcell]]></category>
		<category><![CDATA[inside]]></category>
		<category><![CDATA[subview]]></category>
		<category><![CDATA[table]]></category>
		<category><![CDATA[table inside cell]]></category>
		<category><![CDATA[table view]]></category>
		<category><![CDATA[tableview]]></category>
		<category><![CDATA[tableview cell]]></category>
		<category><![CDATA[tableview inside tableviewcell]]></category>
		<category><![CDATA[tableviewcell]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[uitableview]]></category>
		<category><![CDATA[uitableview inside uitableviewcell]]></category>
		<category><![CDATA[uitableviewcell]]></category>
		<category><![CDATA[uitableviewcontroller]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=62</guid>
		<description><![CDATA[Adding a UITableview as a subview of a UITableViewCell??? Yes, you read it correctly and I typed it correctly. No mistakes have been made here. It sounds strange but once the idea came to my mind I had to do try it out to see if it was possible. I searched online and couldn&#8217;t find [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=62&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Adding a UITableview as a subview of a UITableViewCell??? Yes, you read it correctly and I typed it correctly. No mistakes have been made here. It sounds strange but once the idea came to my mind I had to do try it out to see if it was possible. I searched online and couldn&#8217;t find any help so I decided to write a tutorial. Here it is:<br />
<span id="more-62"></span></p>
<h3>Prep work &#8211; Getting things ready</h3>
<p>First, we shall prepare all the stuff that we would be working with in order to load a UITableView inside a UITableViewCell. Goes without saying but I&#8217;d say it anyway, create/open an Xcode project that has a UITableViewController subclass or has a UIViewController subclass with a UITableView in it.</p>
<h3>Real Work</h3>
<h3><span class="Apple-style-span" style="font-size:15px;font-weight:bold;">Making a custom UITableViewCell</span></h3>
<p>In order to make a custom UITableViewCell, first of all, create a subclass of UITableViewCell, we&#8217;ll name it &#8216;TableViewCell&#8217;. In Xcode 4, File &gt; New &gt; New File and in the dialog select UIViewController subclass and in the &#8216;Next&#8217; dialog type UITableViewCell in the &#8216;subclass&#8217; text field.</p>
<h4>Step 1: Adjust Objects and Properties in Xib File</h4>
<p>Open the xib file of your UITabelViewCell subclass and incase you cannot change the size of the view, delete that view, add a new UIView, and adjust the height to the value you need. I made it 200 so that I can have eight 25 pi long cells inside this cell (25&#215;8=200).</p>
<p>Next thing, change the class of the &#8216;View&#8217; object. Select the &#8216;View&#8217; object, open &#8216;Identity Inspector&#8217;, and type your subclass&#8217;s name i.e. &#8216;TableViewCell&#8217;.</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/changing-class-inside-xib.png"><img class="alignnone size-full wp-image-70" title="Changing Class inside XIB" src="http://iosstuff.files.wordpress.com/2011/06/changing-class-inside-xib.png?w=590&#038;h=327" alt="" width="590" height="327" /></a></p>
<p>After that change the &#8216;File&#8217;s Owner&#8217; to the UITableViewController subclass (or the class that has the table view whose cell this is)</p>
<h3><a href="http://iosstuff.files.wordpress.com/2011/06/changing-files-owner-inside-xib.png"><img class="alignnone size-full wp-image-71" title="Changing Files Owner inside XIB" src="http://iosstuff.files.wordpress.com/2011/06/changing-files-owner-inside-xib.png?w=590&#038;h=327" alt="" width="590" height="327" /></a></h3>
<p>Next create the IBOutlet for the UITableView inside this cell in the header file for UITableViewCell&#8217;s subclass, let&#8217;s name it tableViewInsideCell. In XIB, connect the IBOutlet and set the delegate and dataSource of the tableViewInsideCell to the &#8216;View&#8217; object (whose class we just changed to &#8216;TableViewCell&#8217;) not the File&#8217;s Owner. This is an important step, so be careful. We will only make one connection to the File&#8217;s Owner and that is going to be with the &#8216;View&#8217; object of this xib.</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/connections.png"><img class="alignnone size-full wp-image-72" title="Connections" src="http://iosstuff.files.wordpress.com/2011/06/connections.png?w=590&#038;h=342" alt="" width="590" height="342" /></a></p>
<p>(See how the dataSource, delegate and ref outlet connections are made with the &#8216;TableViewCell&#8217; rather than the File&#8217;s Owner.)</p>
<h4>Step 2: Implement the UITableView Delegate and DataSource in UITableViewCell subclass</h4>
<p>In the header, add the protocol that this class is implementing, i.e. UITableView delegate and data source. So, TableViewCell.h would look like:</p>
<p><code>
<pre>
<span style="color:#888888;">#import &lt;UIKit/UIKit.h&gt;</span>

<span style="color:#888888;">@interface TableViewCell : UITableViewCell &lt;UITableViewDelegate, UITableViewDataSource&gt; {</span>
<span style="color:#888888;">      NSDictionary *data;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">@property (nonatomic, retain) IBOutlet UITableView *tableViewInsideCell;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSDictionary *data;</span>

<span style="color:#888888;">@end</span></pre>
<p></code></p>
<p>Note that there is an NSDictionary object in .h file. This will be used to transfer data from the UITableViewController subclass to the UITableViewCell subclass. Use this dictionary in a switch or an appropriate conditional statement to set appropriate data values for each cell inside the tableView:cellForRowAtIndexPath delegate method.</p>
<p>TableViewCell.m would have the UITableView delegate and dataSource methods. Here is what it would look like:</p>
<p><code>
<pre>
<span style="color:#888888;">#import "TableViewCell.h"</span>

<span style="color:#888888;">@implementation TableViewCell</span>

<span style="color:#888888;">@synthesize tableViewInsideCell;</span>
<span style="color:#888888;">@synthesize data;</span>

<span style="color:#888888;">- (void)dealloc {</span>
<span style="color:#888888;">      [data release];</span>
<span style="color:#888888;">      [tableViewInsideCell release];</span>
<span style="color:#888888;">      [super dealloc];</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {</span>
<span style="color:#888888;">      self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];</span>
<span style="color:#888888;">      if (self) {</span>
<span style="color:#888888;">          // Custom initialization</span>
<span style="color:#888888;">      }</span>
<span style="color:#888888;">      return self;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">#pragma mark - Table view data source</span>
<span style="color:#888888;">- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {</span>
<span style="color:#888888;">      // Return the number of sections.</span>
<span style="color:#888888;">      return 1;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {</span>
<span style="color:#888888;">      // Return the number of rows in the section.</span>
<span style="color:#888888;">      return 8;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{</span>
<span style="color:#888888;">      static NSString *CellIdentifier = @"Cell";</span>
<span style="color:#888888;">      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];</span>
<span style="color:#888888;">      if (cell == nil) {</span>
<span style="color:#888888;">          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
                            reuseIdentifier:CellIdentifier] autorelease];</span>
<span style="color:#888888;">      }</span>

<span style="color:#888888;">      // Configure the cell...</span>

<span style="color:#888888;">     switch (indexPath.row) {</span>
<span style="color:#888888;">        case 0:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Latitude";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Latitude"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 1:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Longitude";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Longitude"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 2:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Speed";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Speed"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 3:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Altitude";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Altitude"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 4:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Date";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Date"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 5:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Time";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Time"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 6:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Course";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Course"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        case 7:</span>
<span style="color:#888888;">            cell.textLabel.text = @"Accuracy";</span>
<span style="color:#888888;">            cell.detailTextLabel.text = [data objectForKey:@"Accuracy"];</span>
<span style="color:#888888;">            break;</span>

<span style="color:#888888;">        default:</span>
<span style="color:#888888;">            break;</span>
<span style="color:#888888;">      }</span>

<span style="color:#888888;">      return cell;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">#pragma mark - Table view delegate</span>
<span style="color:#888888;">-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{</span>
<span style="color:#888888;">    return 25;</span>
<span style="color:#888888;">}</span>
<span style="color:#888888;">@end</span></pre>
<p></code></p>
<h3>Adding the custom UITableViewCell to the Tableview</h3>
<p>In order to add this custom cell to our tableview, the first step is to make an outlet for &#8216;TableViewCell&#8217; (your UITableViewCell&#8217;s subclass) inside your UITableViewController subclass. This is what the &#8216;TableViewController.h&#8217; would look like:</p>
<p><code>
<pre>
<span style="color:#888888;">#import &lt;UIKit/UIKit.h&gt;</span>

<span style="color:#888888;">@class TableViewCell;</span>

<span style="color:#888888;">@interface TableViewController : UITableViewController {</span>
<span style="color:#888888;">    NSArray *dataArray;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">@property (nonatomic, retain) IBOutlet TableViewCell *tableViewCellWithTableView;</span>

<span style="color:#888888;">@end</span></pre>
<p></code></p>
<p>Open TableViewCell.xib and make the &#8216;View&#8217; object&#8217;s (whose class we changed to &#8216;TableViewCell&#8217;) connection with the File&#8217;s Owner. We are doing this because we changed the File&#8217;s Owner class to our UITableViewController subclass. So our cell&#8217;s outlet in the tableview controller header will be connected to the custom cell that we created</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/files-owner-connections.png"><img title="Files Owner Connections" src="http://iosstuff.files.wordpress.com/2011/06/files-owner-connections.png?w=590&#038;h=303" alt="" width="590" height="303" /></a></p>
<p>Making the connections is confusing but its following a simple rule; connections are made with the class that has the outlet declared in it. Here is the list of all connections made in TableViewCell.xib:</p>
<p>1. Custom cell&#8217;s View &lt;-&gt; File&#8217;s Owner | class: TableViewController (because we need the cell object in TableViewController class to assign in tableView:cellForRowAtIndexPath)</p>
<p>2. Tableview inside the cell &lt;-&gt; custom cell&#8217;s View | class: TableViewCell (because the tableView is inside the cell)</p>
<p>3. UITableViewDelegate &amp; UITableViewDataSource &lt;-&gt; custom cell&#8217;s View | class: TableViewCell (because the tableview that is inside the cell has its delegate and data source implemented in our custom cell&#8217;s class. These two connections are very important, if these are made with the File&#8217;s Owner by mistake then remember the File&#8217;s Owner which is tableview controller is implementing its own delegate and data source for the top most tableview, so you wouldn&#8217;t get an error but also not any output)</p>
<p>Anyway, coming back. After making the connection in the xib, add the custom TableViewCell to the table view like so:</p>
<p><code>
<pre>
<span style="color:#888888;">-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{</span>
<span style="color:#888888;">    static NSString *CellIdentifier = @"CellWithTableView";</span>
<span style="color:#888888;">    TableViewCell *cell = (TableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];</span>

<span style="color:#888888;">    if (cell == nil) {</span>
<span style="color:#888888;">        [[NSBundle mainBundle] loadNibNamed:@"TableViewCell" owner:self options:nil];</span>
<span style="color:#888888;">        tableViewCellWithTableView.data = [dataArray objectAtIndex:indexPath.row];</span>
<span style="color:#888888;">        tableViewCellWithTableView.tableViewInsideCell.allowsSelection = NO;</span>
<span style="color:#888888;">        cell = tableViewCellWithTableView;</span>
<span style="color:#888888;">        [cell setNeedsDisplay];</span>
<span style="color:#888888;">    }</span>

<span style="color:#888888;">    return cell;</span>
<span style="color:#888888;">}</span></pre>
<p></code></p>
<p>Note that the cell needs to be loaded from the xib rather than by using the initWithStyle:reuseIdentifier method. Also note that the NSDictionary object called &#8216;data&#8217; that was declared in the custom cell header is being assigned the appropriate element from the dataArray. The dataArray was initialized to have NSDictionary objects, like so:</p>
<p><code>
<pre>
<span style="color:#888888;">    NSDictionary *one = [[[NSDictionary alloc] initWithObjectsAndKeys:@"13.861970", @"Latitude",</span>
<span style="color:#888888;">                          @"100.504250", @"Longitude",</span>
<span style="color:#888888;">                          @"50 kph", @"Speed",</span>
<span style="color:#888888;">                          @"1000 meters", @"Altitude",</span>
<span style="color:#888888;">                          @"12/04/2010", @"Date",</span>
<span style="color:#888888;">                          @"05:45 PM", @"Time",</span>
<span style="color:#888888;">                          @"North west", @"Course",</span>
<span style="color:#888888;">                          @"+/- 10 meters", @"Accuracy", nil] autorelease];</span>

<span style="color:#888888;">    NSDictionary *two = [[[NSDictionary alloc] initWithObjectsAndKeys:@"13.862470", @"Latitude",</span>
<span style="color:#888888;">                          @"100.501389", @"Longitude",</span>
<span style="color:#888888;">                          @"60 kph", @"Speed",</span>
<span style="color:#888888;">                          @"1050 meters", @"Altitude",</span>
<span style="color:#888888;">                          @"12/04/2010", @"Date",</span>
<span style="color:#888888;">                          @"06:15 PM", @"Time",</span>
<span style="color:#888888;">                          @"North", @"Course",</span>
<span style="color:#888888;">                          @"+/- 10 meters", @"Accuracy", nil] autorelease];</span>

<span style="color:#888888;">    NSDictionary *three = [[[NSDictionary alloc] initWithObjectsAndKeys:@"13.861970", @"Latitude",</span>
<span style="color:#888888;">                            @"100.504250", @"Longitude",</span>
<span style="color:#888888;">                            @"70 kph", @"Speed",</span>
<span style="color:#888888;">                            @"1000 meters", @"Altitude",</span>
<span style="color:#888888;">                            @"12/04/2010", @"Date",</span>
<span style="color:#888888;">                            @"06:35 PM", @"Time",</span>
<span style="color:#888888;">                            @"South", @"Course",</span>
<span style="color:#888888;">                            @"+/- 10 meters", @"Accuracy", nil] autorelease];</span>

<span style="color:#888888;">    NSDictionary *four = [[[NSDictionary alloc] initWithObjectsAndKeys:@"13.861970", @"Latitude",</span>
<span style="color:#888888;">                           @"100.504250", @"Longitude",</span>
<span style="color:#888888;">                           @"50 kph", @"Speed",</span>
<span style="color:#888888;">                           @"1050 meters", @"Altitude",</span>
<span style="color:#888888;">                           @"12/04/2010", @"Date",</span>
<span style="color:#888888;">                           @"06:55 PM", @"Time",</span>
<span style="color:#888888;">                           @"South West", @"Course",</span>
<span style="color:#888888;">                           @"+/- 10 meters", @"Accuracy", nil] autorelease];</span>

<span style="color:#888888;">    dataArray = [[NSArray alloc] initWithObjects:one, two, three, four, nil];</span></pre>
<p></code></p>
<p>That is all, just remember to set the cell height to the height of your custom cell.<br />
<code>
<pre>
<span style="color:#888888;">- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{</span>
<span style="color:#888888;">    return 200;</span>
<span style="color:#888888;">}</span>
</pre>
<p></code><br />
With the above dummy data, my table looked like this:</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/tableview-inside-tableviewcell-results.png"><img class="alignnone size-full wp-image-81" title="TableView Inside TableViewCell.Results" src="http://iosstuff.files.wordpress.com/2011/06/tableview-inside-tableviewcell-results.png?w=590" alt=""   /></a></p>
<p>This is the most raw form and can be customized in many ways to look nicer. I hope someone out there finds it useful&#8230;</p>
<p>Trying this and actually succeeding in it made me realize that iOS SDK is flexible and any UIView subclass element to any other UIView subclass. So don&#8217;t be afraid to implement new ideas no matter how wild they might appear. For those eager to try wild stuff, have a look at &#8216;Pulse&#8217;, its a news reader app that won Apple&#8217;s Design Award 2011. This app has horizontally scrollable images and its developers explained that they have used UITableViews to create that. I might try that myself and post a tutorial <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Update: <a href="http://iosstuff.wordpress.com/2011/06/29/creating-pulse-style-scrolling-horizontally-scrolling-uitableview-as-a-subview-of-uitableviewcell/">Pulse-style scrolling tutorial</a> has been published. Enjoy!</p>
<h4>Update</h4>
<p>Borut pointed out that our custom cells with UITableView inside them are not being reused. If we study the code carefully, we will find out that we are not assigning any reuseIdentifier because we are not using the default -initWithStyle:reuseIdentifier method for creating cells. The reuseIdentifier property of UITableViewCell is readonly , we cannot set it. A workaround is to create a getter method in our UITableViewCell subclass for the reuseIdentifier and use the same string being used to dequeue the reusable cells. In our case, this should do:</p>
<p><code>
<pre>
<span style="color:#888888;">- (NSString *) reuseIdentifier {
    return @"Cell";
}</span>
</pre>
<p></code></p>
<p>Note that in this tutorial we are using @&#8221;Cell&#8221; for dequeuing cells in both UITableViewCell subclass and UITableViewController subclass. This needs to return the one we are using in the UITableViewCOntroller subclass because we want to reuse this cell there.</p>
<h4>Update 2</h4>
<p>Thanks a lot for your appreciation. Since there were a lot of requests for code. I&#8217;ve uploaded it to dropbox. Here is the link:<br />
<a href="http://dl.dropbox.com/u/17653793/TableViewInsideCell.zip">http://dl.dropbox.com/u/17653793/TableViewInsideCell.zip</a></p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/tutorial/'>Tutorial</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/cell/'>cell</a>, <a href='http://iosstuff.wordpress.com/tag/custom-tableview-cell/'>custom tableview cell</a>, <a href='http://iosstuff.wordpress.com/tag/custom-uitableviewcell/'>custom uitableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/inside/'>inside</a>, <a href='http://iosstuff.wordpress.com/tag/subview/'>subview</a>, <a href='http://iosstuff.wordpress.com/tag/table/'>table</a>, <a href='http://iosstuff.wordpress.com/tag/table-inside-cell/'>table inside cell</a>, <a href='http://iosstuff.wordpress.com/tag/table-view/'>table view</a>, <a href='http://iosstuff.wordpress.com/tag/tableview/'>tableview</a>, <a href='http://iosstuff.wordpress.com/tag/tableview-cell/'>tableview cell</a>, <a href='http://iosstuff.wordpress.com/tag/tableview-inside-tableviewcell/'>tableview inside tableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/tableviewcell/'>tableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/tutorial-2/'>tutorial</a>, <a href='http://iosstuff.wordpress.com/tag/uitableview/'>uitableview</a>, <a href='http://iosstuff.wordpress.com/tag/uitableview-inside-uitableviewcell/'>uitableview inside uitableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/uitableviewcell/'>uitableviewcell</a>, <a href='http://iosstuff.wordpress.com/tag/uitableviewcontroller/'>uitableviewcontroller</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/62/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=62&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/changing-class-inside-xib.png" medium="image">
			<media:title type="html">Changing Class inside XIB</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/changing-files-owner-inside-xib.png" medium="image">
			<media:title type="html">Changing Files Owner inside XIB</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/connections.png" medium="image">
			<media:title type="html">Connections</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/files-owner-connections.png" medium="image">
			<media:title type="html">Files Owner Connections</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/tableview-inside-tableviewcell-results.png" medium="image">
			<media:title type="html">TableView Inside TableViewCell.Results</media:title>
		</media:content>
	</item>
		<item>
		<title>Are you sure you want to delete &#8216;Angry Birds&#8217;???</title>
		<link>http://iosstuff.wordpress.com/2011/06/29/are-you-sure-you-want-to-delete-angry-birds/</link>
		<comments>http://iosstuff.wordpress.com/2011/06/29/are-you-sure-you-want-to-delete-angry-birds/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 07:27:07 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[angry]]></category>
		<category><![CDATA[angry birds]]></category>
		<category><![CDATA[birds]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[itunes]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=76</guid>
		<description><![CDATA[This morning I was cleaning up my iPad using iTunes. I started with deleting the iPhone apps that got installed in it by mistake during sync. So I selected those apps and hit the &#8216;Apply&#8217; button to sync. Guess what the confirmation pop up said: Being a developer myself, I was wondering did they actually [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=76&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This morning I was cleaning up my iPad using iTunes. I started with deleting the iPhone apps that got installed in it by mistake during sync. So I selected those apps and hit the &#8216;Apply&#8217; button to sync. Guess what the confirmation pop up said:</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/are-you-sure-you-want-to-delete-angry-birds.png"><img class="alignnone size-full wp-image-77" title="Are you sure you want to delete Angry Birds" src="http://iosstuff.files.wordpress.com/2011/06/are-you-sure-you-want-to-delete-angry-birds.png?w=590" alt=""   /></a></p>
<p>Being a developer myself, I was wondering did they actually put a separate &#8216;condition&#8217; to alert users that they are about to delete Angry Birds???</p>
<p>If they did, way to go Angry Birds!!!</p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/general/'>General</a>, <a href='http://iosstuff.wordpress.com/category/uncategorized/'>Uncategorized</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/angry/'>angry</a>, <a href='http://iosstuff.wordpress.com/tag/angry-birds/'>angry birds</a>, <a href='http://iosstuff.wordpress.com/tag/birds/'>birds</a>, <a href='http://iosstuff.wordpress.com/tag/delete/'>delete</a>, <a href='http://iosstuff.wordpress.com/tag/itunes/'>itunes</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/76/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=76&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/06/29/are-you-sure-you-want-to-delete-angry-birds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/are-you-sure-you-want-to-delete-angry-birds.png" medium="image">
			<media:title type="html">Are you sure you want to delete Angry Birds</media:title>
		</media:content>
	</item>
		<item>
		<title>Making a Video (and Photo) Thumbnail Gallery using Three20 Framework</title>
		<link>http://iosstuff.wordpress.com/2011/06/24/making-a-video-and-photo-thumbnail-gallery-using-three20-framework/</link>
		<comments>http://iosstuff.wordpress.com/2011/06/24/making-a-video-and-photo-thumbnail-gallery-using-three20-framework/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 07:34:21 +0000</pubDate>
		<dc:creator>xs2bush</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[gallery]]></category>
		<category><![CDATA[mpmovieplayer]]></category>
		<category><![CDATA[photo]]></category>
		<category><![CDATA[photo scroller]]></category>
		<category><![CDATA[scroll]]></category>
		<category><![CDATA[three20]]></category>
		<category><![CDATA[thumbnail]]></category>
		<category><![CDATA[ttphoto]]></category>
		<category><![CDATA[ttthumbsviewcontroller]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[uiimagepicker]]></category>
		<category><![CDATA[uiimageview]]></category>
		<category><![CDATA[uiscrollview]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://iosstuff.wordpress.com/?p=19</guid>
		<description><![CDATA[There is a huge number of tutorials on how to use three20 to create photo gallery but only very few on how to create photo gallery with thumbnails (they usually focus on creating galleries that start with scrollable photos.) And none at all on creating a video gallery. Therefore, I present this tutorial, which explains [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=19&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>There is a huge number of tutorials on how to use three20 to create photo gallery but only very few on how to create photo gallery with thumbnails (they usually focus on creating galleries that start with scrollable photos.) And none at all on creating a video gallery. Therefore, I present this tutorial, which explains the method of creating a video gallery in detail. Starting from compiling three20 into a project, going through making a thumbnail gallery of photos and finally making a thumbnail gallery containing videos.</p>
<p><span id="more-19"></span></p>
<p>This tutorial has two parts:</p>
<p style="text-align:justify;">1. Creating the photo gallery.</p>
<p style="text-align:justify;">2. Converting this photo gallery to a video Gallery.</p>
<p style="text-align:justify;">So, lets begin&#8230;</p>
<h1>1. Creating Photo Gallery</h1>
<h3>Step 1: Create an Xcode Project</h3>
<p>If you do not already have a project in which you want to create the gallery, now would be the time to create one. If you are starting from scratch, create a &#8216;Window-based&#8217; project in Xcode. Lets name it &#8220;PhotoVideoGallery&#8221;, which is the name that will be used from now on in the tutorial.</p>
<h3>Step 2: Download and build the three20 framework.</h3>
<p>First of all, download <a href="https://github.com/facebook/three20" target="_blank">the latest version of three20 from github.</a> Now that we have three20, we need to add it to our project.</p>
<p><a href="http://three20.info/article/2010-10-06-Adding-Three20-To-Your-Project" target="_blank">This little tutorial by the creator of three20</a> is quite convenient for building it. Here are the main steps so you don&#8217;t have to navigate away:</p>
<p>1.  Make a new folder on the desktop and copy both three20 and your project (a copy preferably) into it.</p>
<p>2. Open terminal and move to the desktop using this command</p>
<p><span style="color:#808080;"><code>cd ~/Desktop</code></span></p>
<p>3. Three20 includes a python script that adds it to Xcode iOS projects. We can run the script by running this command in the terminal:</p>
<p><span style="color:#808080;"><code> python three20/src/scripts/ttmodule.py -p PhotoVideoGallery/PhotoVideoGallery.xcodeproj Three20</code></span></p>
<p>4. What? there&#8217;s no step 4 <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Simple as that!!!</p>
<p>Note: If you do not want to copy/move your project, you can build three20 into it using this terminal command replacing your specific paths and project&#8217;s name:</p>
<p><span style="color:#808080;"><code> python path/to/three20/src/scripts/ttmodule.py -p path/to/myProjectName.xcodeproj Three20</code></span></p>
<p>You might get an alert when you open your project that your project has been altered from an outside entity. In that case, you need to click on the &#8220;Read from Disk&#8221; button.</p>
<h3>Step 3: Start making the gallery, finally</h3>
<p>First a word on how this works. We need a thumbnail gallery, which needs a source that provides it the photos to display. This source needs photos so it can give them to the gallery. So we have to make three new classes, one for the photo, one for the photo source and one for the gallery.</p>
<h4>The Photo Class</h4>
<p>Create a subclass called &#8220;Photo&#8221; of NSObject and make it conform to the protocol &lt;<strong>TTPhoto</strong>&gt;. Now according to this protocol, our photo must have the following attributes and methods:</p>
<pre><code><span style="color:#808080;">* The photo source that the photo belongs to.</span>
<span style="color:#808080;"> @property (nonatomic, assign) id photoSource;</span>

<span style="color:#808080;"> * The size of the photo.</span>
<span style="color:#808080;"> @property (nonatomic) CGSize size;</span>

<span style="color:#808080;"> * The index of the photo within its photo source.</span>
<span style="color:#808080;"> @property (nonatomic) NSInteger index;</span>

<span style="color:#808080;"> * The caption of the photo.</span>
<span style="color:#808080;"> @property (nonatomic, copy) NSString* caption;</span>

<span style="color:#808080;"> * Gets the URL of one of the differently sized versions of the photo.</span>
<span style="color:#808080;"> - (NSString*)URLForVersion:(TTPhotoVersion)version;</span>
</code></pre>
<p>we are going to use an -init method to set these attributes. So our Photo.h looks like this</p>
<p><code>
<pre><span style="color:#808080;">
@interface Photo : NSObject  {
      NSString *_caption;
      NSString *_urlLarge;
      NSString *_urlSmall;
      NSString *_urlThumb;
      id  _photoSource;
      CGSize _size;
      NSInteger _index;
}
@property (nonatomic, copy) NSString *caption;
@property (nonatomic, copy) NSString *urlLarge;
@property (nonatomic, copy) NSString *urlSmall;
@property (nonatomic, copy) NSString *urlThumb;
@property (nonatomic, assign) id  photoSource;
@property (nonatomic) CGSize size;
@property (nonatomic) NSInteger index;
- (id)initWithCaption:(NSString *)caption urlLarge:(NSString *)urlLarge
urlSmall:(NSString *)urlSmall urlThumb:(NSString *)urlThumb size:(CGSize)size;
@end</span></pre>
<p></code></p>
<p>and Photo.m looks like this:<br />
<code>
<pre>
<span style="color:#888888;">#import "Photo.h"</span>

<span style="color:#888888;">@implementation Photo</span>
<span style="color:#888888;">@synthesize caption = _caption;</span>
<span style="color:#888888;">@synthesize urlLarge = _urlLarge;</span>
<span style="color:#888888;">@synthesize urlSmall = _urlSmall;</span>
<span style="color:#888888;">@synthesize urlThumb = _urlThumb;</span>
<span style="color:#888888;">@synthesize photoSource = _photoSource;</span>
<span style="color:#888888;">@synthesize size = _size;</span>
<span style="color:#888888;">@synthesize index = _index;</span>

<span style="color:#888888;">- (id)initWithCaption:(NSString *)caption urlLarge:(NSString *)urlLarge
                    urlSmall:(NSString *)urlSmall urlThumb:(NSString *)urlThumb size:(CGSize)size {</span>

<span style="color:#888888;">    if ((self = [super init])) {</span>
<span style="color:#888888;">       self.caption = caption;</span>
<span style="color:#888888;">       self.urlLarge = urlLarge;</span>
<span style="color:#888888;">       self.urlSmall = urlSmall;</span>
<span style="color:#888888;">       self.urlThumb = urlThumb;</span>
<span style="color:#888888;">       self.size = size;</span>
<span style="color:#888888;">       self.index = NSIntegerMax;</span>
<span style="color:#888888;">       self.photoSource = nil;</span>
<span style="color:#888888;">    }</span>
<span style="color:#888888;">    return self;</span>
<span style="color:#888888;">    }</span>

<span style="color:#888888;">- (void) dealloc {</span>
<span style="color:#888888;">     self.caption = nil;</span>
<span style="color:#888888;">     self.urlLarge = nil;</span>
<span style="color:#888888;">     self.urlSmall = nil;</span>
<span style="color:#888888;">     self.urlThumb = nil;</span>
<span style="color:#888888;">     [super dealloc];</span>
<span style="color:#888888;"> }</span>

<span style="color:#888888;">#pragma mark TTPhoto</span>

<span style="color:#888888;">- (NSString*)URLForVersion:(TTPhotoVersion)version {</span>
<span style="color:#888888;">     switch (version) {</span>
<span style="color:#888888;">       case TTPhotoVersionLarge:</span>
<span style="color:#888888;">         return _urlLarge;</span>
<span style="color:#888888;">       case TTPhotoVersionMedium:</span>
<span style="color:#888888;">         return _urlLarge;</span>
<span style="color:#888888;">       case TTPhotoVersionSmall:</span>
<span style="color:#888888;">         return _urlSmall;</span>
<span style="color:#888888;">       case TTPhotoVersionThumbnail:</span>
<span style="color:#888888;">         return _urlThumb;</span>
<span style="color:#888888;">       default:</span>
<span style="color:#888888;">         return nil;</span>
<span style="color:#888888;">     }</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">@end</span></pre>
<p></code></p>
<h4>The Photo Source Class</h4>
<p>Create a subclass called &#8220;PhotoSource&#8221; of <strong>TTURLRequestModel</strong> (so that we can also download photos from a server using the same class) and make it conform to the protocol &lt;<strong>TTPhotoSource</strong>&gt;. Now according to this protocol, our photo must have the following attributes and methods:</p>
<pre><code>
<span style="color:#888888;">* The title of this collection of photos.</span>
<span style="color:#888888;"> @property (nonatomic, copy) NSString* title;</span>

<span style="color:#888888;">* The total number of photos in the source, independent of the number that have been loaded.</span>
<span style="color:#888888;"> @property (nonatomic, readonly) NSInteger numberOfPhotos;</span>

<span style="color:#888888;">* The maximum index of photos that have already been loaded.</span>
<span style="color:#888888;"> @property (nonatomic, readonly) NSInteger maxPhotoIndex;</span>

<span style="color:#888888;">- (id)photoAtIndex:(NSInteger)index;</span>
</code></pre>
<p>So our PhotoSource.h looks like:<br />
<code>
<pre>
<span style="color:#888888;">@interface PhotoSource : TTURLRequestModel  {</span>
<span style="color:#888888;">   NSString *_title;</span>
<span style="color:#888888;">   NSArray *_photos;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">@property (nonatomic, copy) NSString *title;</span>
<span style="color:#888888;">@property (nonatomic, retain) NSArray *photos;</span>
<span style="color:#888888;">+ (PhotoSet*)samplePhotoSet;</span>

<span style="color:#888888;">@end</span></pre>
<p></code></p>
<p>and our PhotoSource.m should look like:<br />
<code>
<pre>
<span style="color:#888888;">#import "PhotoSource.h"</span>
<span style="color:#888888;">#import "Photo.h"</span>

<span style="color:#888888;">@implementation PhotoSource</span>
<span style="color:#888888;">@synthesize title = _title;</span>
<span style="color:#888888;">@synthesize photos = _photos;</span>

<span style="color:#888888;">- (id) initWithTitle:(NSString *)title photos:(NSArray *)photos {</span>
<span style="color:#888888;">     if ((self = [super init]))</span>
<span style="color:#888888;">       self.title = title;</span>
<span style="color:#888888;">       self.photos = photos;</span>
<span style="color:#888888;">       for(int i = 0; i &lt; _photos.count; ++i) {</span>
<span style="color:#888888;">         Photo *photo = [_photos objectAtIndex:i];</span>
<span style="color:#888888;">         photo.photoSource = self;</span>
<span style="color:#888888;">         photo.index = i;</span>
<span style="color:#888888;">       }</span>
<span style="color:#888888;">     }</span>
<span style="color:#888888;">     return self;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (void) dealloc {</span>
<span style="color:#888888;">     self.title = nil;</span>
<span style="color:#888888;">     self.photos = nil;</span>
<span style="color:#888888;">     [super dealloc];</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">#pragma mark TTModel</span>

<span style="color:#888888;">- (BOOL)isLoading {</span>
<span style="color:#888888;">     return FALSE;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (BOOL)isLoaded {</span>
<span style="color:#888888;">     return TRUE;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">#pragma mark TTPhotoSource</span>

<span style="color:#888888;">- (NSInteger)numberOfPhotos {</span>
<span style="color:#888888;">     return _photos.count;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (NSInteger)maxPhotoIndex {</span>
<span style="color:#888888;">     return _photos.count-1;</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">- (id)photoAtIndex:(NSInteger)photoIndex {</span>
<span style="color:#888888;">     if (photoIndex &lt; _photos.count) {</span>
<span style="color:#888888;">         return [_photos objectAtIndex:photoIndex];</span>
<span style="color:#888888;">     } else {</span>
<span style="color:#888888;">         return nil;</span>
<span style="color:#888888;">     }</span>
<span style="color:#888888;">}</span>

<span style="color:#888888;">static PhotoSource *samplePhotoSet = nil;</span>

<span style="color:#888888;">+ (PhotoSet*) samplePhotoSet {</span>
<span style="color:#888888;">     @synchronized(self) {</span>
<span style="color:#888888;">       if (samplePhotoSet == nil) {</span>
<span style="color:#888888;">         Photo *firstPhoto = [[[Photo alloc] initWithCaption:@"Lake"
                                                     urlLarge:@"bundle://Lake.jpg"
                                                     urlSmall:nil
                                                     urlThumb:@"bundle://Lake_Thumb.png"
                                                     size:CGSizeMake(1024, 768)] autorelease];</span>

<span style="color:#888888;">         Photo *secondPhoto = [[[Photo alloc] initWithCaption:@"Shed"
                                                     urlLarge:@"bundle://Shed.jpg"
                                                     urlSmall:nil
                                                     urlThumb:@"bundle://Shed_Thumb.png"
                                                     size:CGSizeMake(768, 1024)] autorelease];</span>

<span style="color:#888888;">         Photo *thirdPhoto = [[[Photo alloc] initWithCaption:@"Tree"
                                                     urlLarge:@"bundle://Tree.jpg"
                                                     urlSmall:nil
                                                     urlThumb:@"bundle://Tree_Thumb.png"
                                                     size:CGSizeMake(683, 1024)] autorelease];</span>

<span style="color:#888888;">         NSArray *photos = [NSArray arrayWithObjects:firstPhoto, secondPhoto, thirdPhoto, nil];</span>
<span style="color:#888888;">         samplePhotoSet = [[self alloc] initWithTitle:@"Pictures" photos:photos];</span>
<span style="color:#888888;">       }</span>
<span style="color:#888888;">     }</span>
<span style="color:#888888;">     return samplePhotoSet;</span>
<span style="color:#888888;"> }</span>
<span style="color:#888888;">@end</span></pre>
<p></code></p>
<p>Note: Replace the image names, paths, and sizes for this to work.</p>
<p>To display a thumbnail gallery we need to subclass &#8216;<strong>TTThumbsViewController</strong>&#8216; class of three20. So,</p>
<p>1. Follow the old creating new file routine, File &gt; New &gt; New File. Select the &#8216;UIViewController subclass&#8217; when it asks the template for your new file. In the next step, type &#8220;<strong>TTThumbsViewController</strong>&#8221; in the &#8216;subclass&#8217; text field. Give your class a name, we&#8217;ll name it &#8220;ThumbsViewController&#8221;</p>
<p>2. Now, ThumbsViewController needs a photoSource so add it as an attribute to our class. ThumbsViewController.h looks like:<br />
<code>
<pre>
<span style="color:#888888;">#import </span>
<span style="color:#888888;">@class PhotoSource;</span>

<span style="color:#888888;">@interface ThumbsViewController : TTThumbsViewController {</span>
<span style="color:#888888;">      PhotoSource *_myPhotoSource;</span>
<span style="color:#888888;">}</span>
<span style="color:#888888;">@property (nonatomic, retain) PhotoSource *myPhotoSource;</span>
<span style="color:#888888;">@end</span></pre>
<p></code></p>
<p>and in the implementation we set the photo source to ours and ThumbsViewController.m looks like:</p>
<pre><code><span style="color:#888888;">
#import "ThumbsViewController.h"
#import "PhotoSource.h"</span>

<span style="color:#888888;">@implementation ThumbsViewController</span>
<span style="color:#888888;">@synthesize myPhotoSource;</span>

<span style="color:#888888;">- (void) viewDidLoad {</span>
<span style="color:#888888;">     self.myPhotoSource = [PhotoSource samplePhotoSet];</span>
<span style="color:#888888;"> }</span>

<span style="color:#888888;">- (void) dealloc {</span>
<span style="color:#888888;">     self.myPhotoSource = nil;</span>
<span style="color:#888888;">     [super dealloc];</span>
<span style="color:#888888;"> }</span>

<span style="color:#888888;">@end</span></code></pre>
<p>All is done, except we should display ThumbsViewController somewhere in order to be able to view our gallery. So, we add this to our app delegate :</p>
<p><code>
<pre>
<span style="color:#888888;">UINavigationController *navigationController = [[UINavigationController alloc]
                             initWithRootViewController:[[ThumbsViewController alloc] init]];</span>
<span style="color:#888888;">[self.window navigationController];</span>
<span style="color:#888888;">[navigationController release];</span>
</pre>
<p></code><br />
Here is what it should look like and when a thumbnail is tapped, the photos are opened in a scroller, just like int the &#8216;Photos&#8217; app:</p>
<p><a href="http://iosstuff.files.wordpress.com/2011/06/screen-shot-2011-06-21-at-4-46-41-pm1.png"><img class="size-full wp-image-45 alignnone" title="Screen shot 2011-06-21 at 4.46.41 PM" src="http://iosstuff.files.wordpress.com/2011/06/screen-shot-2011-06-21-at-4-46-41-pm1.png?w=590" alt=""   /></a></p>
<h1>2. Converting it to a Video Gallery</h1>
<p>Now, we shall convert this photo gallery we just made into a video gallery. So what we have to do is, in <strong>TTThumbsViewController</strong>, find the method that is called when a thumbnail is tapped and override it in our ThumbsViewController (our <strong>TTThumbsViewController</strong> subclass). The function that we&#8217;re looking for is <strong>thumbsTableViewCell: didSelectPhoto:</strong>. So Add this code to your ThumbsViewController:<br />
<code>
<pre>
<span style="color:#888888;">- (void)thumbsTableViewCell:(TTThumbsTableViewCell*)cell didSelectPhoto:(id)photo {</span>
<span style="color:#888888;">        NSString *videoName = [photo caption];</span>
<span style="color:#888888;">        NSString *videoPath = [[NSBundle mainBundle] pathForResource:videoName ofType:@"m4v"];</span>
<span style="color:#888888;">        VideoPlayerViewController *videoController = [[VideoPlayerViewController alloc]
                               initWithPath:videoPath];</span>
<span style="color:#888888;">        [self presentModalViewController:videoController animated:YES];</span>
<span style="color:#888888;">        [videoController readyPlayer];</span>
<span style="color:#888888;">}</span>
</pre>
<p></code><br />
Note that photo&#8217;s caption that we had previously set in <strong>initWithCaption: urlLarge: urlSmall urlThumb size:</strong> inside the PhotoSource class is being used as the name of the video in this case. The ivar caption is displayed in the photo scroller. Since we are not loading the photo scroller in this case, we can use it to store the names of our videos so that we can later use them to get required video from the app bundle. Also note that VideoPlayerViewController is another UIViewController subclass that manages the MPMoviePlayer. The player can also be initialized and loaded here directly.</p>
<p><strong>Legend</strong>: Bolded items are keywords specific to <strong>Three20</strong> framework so they can be distinguished from our subclasses</p>
<p><strong>Code Courtesy for Photo and PhotoSource code</strong>: Ray Wenderlich<br />
<strong> Code Courtesy for ThumbnailViewController code: </strong><a href="https://github.com/crigor/three20_examples" target="_blank">https://github.com/crigor/three20_examples</a></p>
<br />Filed under: <a href='http://iosstuff.wordpress.com/category/tutorial/'>Tutorial</a> Tagged: <a href='http://iosstuff.wordpress.com/tag/gallery/'>gallery</a>, <a href='http://iosstuff.wordpress.com/tag/mpmovieplayer/'>mpmovieplayer</a>, <a href='http://iosstuff.wordpress.com/tag/photo/'>photo</a>, <a href='http://iosstuff.wordpress.com/tag/photo-scroller/'>photo scroller</a>, <a href='http://iosstuff.wordpress.com/tag/scroll/'>scroll</a>, <a href='http://iosstuff.wordpress.com/tag/three20/'>three20</a>, <a href='http://iosstuff.wordpress.com/tag/thumbnail/'>thumbnail</a>, <a href='http://iosstuff.wordpress.com/tag/ttphoto/'>ttphoto</a>, <a href='http://iosstuff.wordpress.com/tag/ttthumbsviewcontroller/'>ttthumbsviewcontroller</a>, <a href='http://iosstuff.wordpress.com/tag/tutorial-2/'>tutorial</a>, <a href='http://iosstuff.wordpress.com/tag/uiimagepicker/'>uiimagepicker</a>, <a href='http://iosstuff.wordpress.com/tag/uiimageview/'>uiimageview</a>, <a href='http://iosstuff.wordpress.com/tag/uiscrollview/'>uiscrollview</a>, <a href='http://iosstuff.wordpress.com/tag/video/'>video</a>, <a href='http://iosstuff.wordpress.com/tag/xcode/'>xcode</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iosstuff.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iosstuff.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iosstuff.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iosstuff.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iosstuff.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iosstuff.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iosstuff.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iosstuff.wordpress.com/19/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iosstuff.wordpress.com&amp;blog=24323052&amp;post=19&amp;subd=iosstuff&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iosstuff.wordpress.com/2011/06/24/making-a-video-and-photo-thumbnail-gallery-using-three20-framework/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0d39274adf1f9f35a9e7652c94e4f8d?s=96&#38;d=retro&#38;r=G" medium="image">
			<media:title type="html">xs2bush</media:title>
		</media:content>

		<media:content url="http://iosstuff.files.wordpress.com/2011/06/screen-shot-2011-06-21-at-4-46-41-pm1.png" medium="image">
			<media:title type="html">Screen shot 2011-06-21 at 4.46.41 PM</media:title>
		</media:content>
	</item>
	</channel>
</rss>
