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

<channel>
	<title>codesofa &#187; sdk</title>
	<atom:link href="http://codesofa.com/blog/archive/tag/sdk/feed" rel="self" type="application/rss+xml" />
	<link>http://codesofa.com</link>
	<description>chaotic. pragmatic. smart(ass).</description>
	<lastBuildDate>Wed, 04 Aug 2010 16:05:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Look! UIAlertView is dating UITableView!</title>
		<link>http://codesofa.com/blog/archive/2009/07/15/look-uialertview-is-dating-uitableview.html</link>
		<comments>http://codesofa.com/blog/archive/2009/07/15/look-uialertview-is-dating-uitableview.html#comments</comments>
		<pubDate>Wed, 15 Jul 2009 19:51:26 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[sdk]]></category>
		<category><![CDATA[UIAlertView]]></category>
		<category><![CDATA[UITableView]]></category>

		<guid isPermaLink="false">http://codesofa.com/?p=202</guid>
		<description><![CDATA[As you may have guessed, this is about UIAlertView containing a UITableView. Since I started playing around with GameKit, I had the issue that I couldn&#8217;t use the PeerPicker with Client/Server stuff.. I can&#8217;t really get into the stuff we are doing and where we are using it &#8211; but I can offer you some [...]]]></description>
			<content:encoded><![CDATA[<p>As you may have guessed, this is about UIAlertView containing a UITableView. Since I started playing around with GameKit, I had the issue that I couldn&#8217;t use the PeerPicker with Client/Server stuff..<br />
I can&#8217;t really get into the stuff we are doing and where we are using it &#8211; but I can offer you some trick and code to have a UIAlertView displayed with a fully controllable UITableView.</p>
<p>I started off with making it a decorator.. After 20&#8242; I had to give up, because it was just too complicated to decorate objects where you don&#8217;t really know what&#8217;s going on. So I had to subclass it &#8211; unfortunately, but anyway..</p>
<p>Let&#8217;s take a look at what you would probably like to have..</p>
<h3 class="codetitle">Client</h3>
<pre><code class="prettyprint">UIAlertTableView *alert = [[UIAlertTableView alloc] initWithTitle:@"Select Option"
    message:@"select option or create one"
    delegate:self
    cancelButtonTitle:@"Cancel"
    otherButtonTitles:@"Create", nil];
alert.tableDelegate = self;
alert.dataSource = self;
alert.tableHeight = 120;
</code></pre>
<p>And this should be the result:</p>
<p><a href="http://codesofa.com/files/2009/07/alerttable1.png" rel="lightbox"><img src="http://codesofa.com/files/2009/07/alerttable1-300x156.png" alt="" title="alerttable1" width="300" height="156" class="alignnone size-medium wp-image-209" /></a></p>
<p>Alright, so, we just add a UITableView to the UIAlertView as a Subview, right? Hold on, Tiger :)<br />
First of all, if we set the message to nil, we want to have this:</p>
<p><a href="http://codesofa.com/files/2009/07/alerttable2.png" rel="lightbox"><img src="http://codesofa.com/files/2009/07/alerttable2-300x156.png" alt="" title="alerttable2" width="300" height="156" class="alignnone size-medium wp-image-210" /></a></p>
<p>And if we rotate, we want to have the nice effects! Like this:</p>
<p><a href='http://screencast.com/t/Diw6UmXi4' >Rotate Animation</a></p>
<p>If you only want to grab the code without BlahBlah: <a href="http://bitbucket.org/marcammann/uialerttableview/src/">UIAlertTableView on Bitbucket.org</a> (btw. I switched to bitbucket.org &#8211; but that&#8217;s another story)</p>
<p>So, let&#8217;s look at the code a bit:</p>
<h3 class="codetitle">UIAlertTableView.h</h3>
<pre><code class="prettyprint">
#import &lt;UIKit/UIKit.h&gt;

@class UIAlertView;

@interface UIAlertTableView : UIAlertView {
	// The Alert View to decorate
	UIAlertView *alertView;

	// The Table View to display
	UITableView *tableView;

	// Height of the table
	int tableHeight;

	// Space the Table requires (incl. padding)
	int tableExtHeight;

	id<UITableViewDataSource> dataSource;
	id<UITableViewDelegate> tableDelegate;
}

@property (nonatomic, assign) id dataSource;
@property (nonatomic, assign) id tableDelegate;

@property (nonatomic, readonly) UITableView *tableView;
@property (nonatomic, assign) int tableHeight;

- (void)prepare;

@end
</code></pre>
<p>You see: we subclass UIAlertView, we have a UITableView, we have a delegate which needs to implement the protocol as well as a dataSource. Straight forward, I&#8217;d say&#8230;</p>
<p>Now, as for the implementation, one would think: just overload the &#8220;show&#8221; method and insert the TableView as a subview etc. Well, that works &#8211; NOT. First of all: you have to resize your AlertView, then you have to move the buttons down and then you have to place the tableView somewhere (esoteric?).<br />
OkOk, just overwrite the drawRect then? You are getting closer!<br />
But, first, let&#8217;s have a look at the prepare method.</p>
<h3 class="codetitle">UIAlertTableView.m:prepare</h3>
<pre><code class="prettyprint">
- (void)prepare {
	if (tableHeight == 0) {
		tableHeight = 150.0f;
	}

	// Calculate the TableViewHeight with padding
	tableExtHeight = tableHeight + 2 * kTablePadding;

	tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
	tableView.delegate = tableDelegate;
	tableView.dataSource = dataSource;	

	// Insert it as the first subview
	[self insertSubview:tableView atIndex:0];
}
</code>
</pre>
<p>This code creates the TableView but does not set a real frame yet. It sets the given DataSource and Delegate. To be totally correct, there should be a custom setTableDelegate / setDataSource method which changes them in the tableView &#8211; but this is left as an exercise to the reader :)<br />
After the creation, we insert the tableView as the very first subview of the alertView &#8211; so we know where to find it again and that nothing is hidden because of the tableView.</p>
<p>Now comes the tricky part: drawing.<br />
For that, we use a private API call to the AlertView, called layoutAnimated:(BOOL)animated.<br />
We overload it in our custom subclass because the initial drawing and the drawing on setNeedsLayout goes through that method.<br />
After that method is called, all the elements that belong to the AlertView (title, message, buttons &#8230;) are arranged, so we can use those values for our next computations.</p>
<p>So, this is how it goes:</p>
<h3 class="codetitle">UIAlertTableView.m:layoutAnimated</h3>
<pre><code class="prettyprint">
- (void)layoutAnimated:(BOOL)fp8 {
	[super layoutAnimated:fp8];
	[self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y - tableExtHeight/2, self.frame.size.width, self.frame.size.height + tableExtHeight)];

	// We get the lowest non-control view (i.e. Labels) so we can place the table view just below
	UIView *lowestView = [self.subviews objectAtIndex:0];
	int i = 0;
	while (![[self.subviews objectAtIndex:i] isKindOfClass:[UIControl class]]) {
		UIView *v = [self.subviews objectAtIndex:i];
		if (lowestView.frame.origin.y + lowestView.frame.size.height < v.frame.origin.y + v.frame.size.height) {
			lowestView = v;
		}

		i++;
	}

	// TODO: calculate this value
	CGFloat tableWidth = 262.0f;

	tableView.frame = CGRectMake(11.0f, lowestView.frame.origin.y + lowestView.frame.size.height + 2 * kTablePadding, tableWidth, tableHeight);

	for (UIView *sv in self.subviews) {
		// Move all Controls down
		if ([sv isKindOfClass:[UIControl class]]) {
			sv.frame = CGRectMake(sv.frame.origin.x, sv.frame.origin.y + tableExtHeight, sv.frame.size.width, sv.frame.size.height);
		}
	}
}
</code>
</pre>
<p>Step by step: first, we call the superclass - so everything gets arranged.<br />
Then, we set a new frame for the AlertView, which is the same frame + tableHeight + padding. But we also need to rearrange the frame - which is half of that additional height.<br />
After that, we compute the lowest "sitting" normal view - no control object - in the alert view. We loop through it, until we find the first control element - which are usually the buttons, because they are added at the end. You could loop through all views and get the lowest from any non-UIControl objects. But this works :)<br />
This position is used to place the TableView at the correct position - whether you have a message, a title or whatever there.. but it needs to be above the buttons - UI standards.<br />
To be above the buttons, we need to rearrange the buttons, and this is what happens: all UIControl object in the AlertView are moved down by the size we added to the AlertView frame - the complete TableHeight. And this is it.<br />
We resize the AlertView, calculate the position where the TableView is supposed to be inserted at and then move the buttons. If we rotate, this gets calculated again and nicely rearranged.</p>
<p>Note: you can apply the very same method for any other UIView object you want to insert into an UIAlertView.. Be it TextField or ImageView or whatever. (For textField, you should use their private APIs though)</p>
<p>Again, code is here: <a href="http://bitbucket.org/marcammann/uialerttableview/src/">Code on Bitbucket.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2009/07/15/look-uialertview-is-dating-uitableview.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Beer for Issue!</title>
		<link>http://codesofa.com/blog/archive/2009/02/27/beer-for-issue.html</link>
		<comments>http://codesofa.com/blog/archive/2009/02/27/beer-for-issue.html#comments</comments>
		<pubDate>Fri, 27 Feb 2009 14:42:42 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[Information]]></category>
		<category><![CDATA[Transport]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[0.9.0]]></category>
		<category><![CDATA[appstore]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[issues]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://codesofa.com/?p=185</guid>
		<description><![CDATA[Hi there.. It&#8217;s been a while and I&#8217;m still pretty busy, but I feel like I have to write something this very sunny afternoon. There are a lot of projects in the pipeline, a few will come out sooner or later :) One project which is still making my head go up and down and [...]]]></description>
			<content:encoded><![CDATA[<p>Hi there.. It&#8217;s been a while and I&#8217;m still pretty busy, but I feel like I have to write something this very sunny afternoon.<br />
There are a lot of projects in the pipeline, a few will come out sooner or later :)<br />
One project which is still making my head go up and down and left and right is Transport. I somehow managed to get on the <a href="http://www.bestofswissweb.ch/shortlist">shortlist of this years Best of Swiss Web</a>. Besides that, I found a still secret partner for the work on Transport. There has been a lot of development, of which not all is on github yet &#8211; some parts are just not ready for open source deployment. (But they will be!)<br />
Today, I want to talk about my beta testers &#8211; they are great. Most of them anyway :)</p>
<p>I&#8217;m facing two problems with them though. First, I don&#8217;t know all of them &#8211; which is unfortunate. There are some I just cannot meet because they live in the south of Uguhagdarbia (not quite..) but there are  others which live in the very same city &#8211; Zurich &#8211; and I still haven&#8217;t managed to meet them.</p>
<p>Second, some of them just want to have an application before everyone else does &#8211; (no offense guys..) &#8211; and what I want in return is feedback &#8211; and not always get it. However, there are some very serious beta testers and I really want to thank you :)</p>
<p>This night, I had an insanly great idea to solve both problems at once and actually solve a third problem: get more testers :)</p>
<p>So what is it about? There have been rumors, that Transport will be ready at the end of march, and so I will need testers in the next few weeks.<br />
<em><strong>This is why I proudly announce the &#8220;Beer for Issue&#8221; program :)</strong></em> What is that? My idea is: If you sign up until the 20th of march on beta[AT]codesofa.com with your UDID, name and e-mail (see <a href="http://codesofa.com/code/transport">Apply for Beta</a>) and you are among the first 70 to sign up, then you get into the &#8220;program&#8221;. After that, you will receive a copy of &#8220;Transport.app&#8221; Beta for the iPhone somewhen after the 20th.</p>
<p>`HOLY CRAP WHERE IS THAT BEER!` &#8211; yes, we are coming to it. After that, you will receive instructions of how to report bugs/issues/whatsoever to me :) Since I really appreciate your time and haven&#8217;t figured out a way to show that to you, <span style="color: #000000;"><span style="text-decoration: underline;"><strong>I offer Beer. Free Beer actually</strong>.</span></span> :) The exact rules have to be determined after the signup is completed, but I plan to give out a beer for every fibonacci number of issues you report, starting at 3.. As long as they are not a duplicate. With &#8220;improvement&#8221; requests, I&#8217;m not so sure yet. That will be a mater of personal oppinion, if they are great, I&#8217;ll buy you 2 beers, if they are ridiculous, you&#8217;ll have to buy me 4 to make me implement it ;)</p>
<p>Let&#8217;s make an example: You report 3 issues &#8211; get 1 beer, 4 issues &#8211; still only 1, 5 issues (2+3) &#8211; get 2 beers, 6 &amp; 7 issues &#8211; 2 beers, 8 issues &#8211; 3 beers etc. Maybe there will be more beer &#8211; I don&#8217;t know yet :)</p>
<p>`IS HE INSANE?!` &#8211; No, not at all. This will force me to write good code, so I don&#8217;t have to buy a lot of beers and besides that, I get to know all of you :) It&#8217;s like a release party.. But more fun because everyone worked on it..</p>
<p>In short:</p>
<ul>
<li>Write me an E-Mail with you iPhone/iPod UDID, your name and your e-mail address until march 20th, 2009 to beta[AT]codesofa.com</li>
<li>Report issues on &#8220;Transport&#8221; iPhone app.</li>
<li>Get paid in beer &#8211; and yes, for ladies there will be a special arrangement possible :)</li>
</ul>
<p>Have fun.</p>
<p>btw.: There is some special ruling for the last testing-period testers, I will figure something out &#8211; but you&#8217;ll get more ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2009/02/27/beer-for-issue.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>There are friends and there are friends..</title>
		<link>http://codesofa.com/blog/archive/2008/08/22/there-are-friends-and-there-are-friends.html</link>
		<comments>http://codesofa.com/blog/archive/2008/08/22/there-are-friends-and-there-are-friends.html#comments</comments>
		<pubDate>Thu, 21 Aug 2008 23:06:44 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[GottaGo]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[nearby]]></category>
		<category><![CDATA[sbb]]></category>
		<category><![CDATA[sdk]]></category>
		<category><![CDATA[stations]]></category>

		<guid isPermaLink="false">http://lab.codesofa.com/blog/archive/2008/08/22/there-are-friends-and-there-are-friends.html</guid>
		<description><![CDATA[If you&#8217;ve ever used &#8220;GottaGo&#8220;, you might have experienced it from time to time: The stations around you disappear on the &#8220;Closest&#8221; Screen. Why does this happen? Let me explain. So far, I used the nearby search from Google to get a list of stations around you. Fairly simple. But.. SBB.ch does i.e. not understand [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever used &#8220;<a href="http://liip.to/gottago">GottaGo</a>&#8220;, you might have experienced it from time to time: The stations around you disappear on the &#8220;Closest&#8221; Screen.</p>
<p>Why does this happen? Let me explain.</p>
<p>So far, I used the <a href="http://maps.google.com">nearby search</a> from <a href="http://google.com">Google</a> to get a list of stations around you. Fairly simple. But.. <a href="http://sbb.ch">SBB.ch</a> does i.e. not understand &#8220;Bäckeranlage&#8221; but &#8220;Zürich, Bäckeranlage&#8221; which makes sense. But Google only provides &#8220;Bäckeranlage&#8221; &#8211; not so nice to map here. I&#8217;ve seen a comment in the AppStore from someone who noted this problem.. And he is right. This gave me a hard time.. [The fact that I'm in the exam session was no helpful either but nevermind :)]</p>
<p>How was the problem solved so far? With reverse geocoding. With the (great) API provided by <a href="http://www.geonames.org">geonames.org</a>, I could more or less flatten this problems out. More or less? Yes. In the logs (Yes, sorry, I keep logfiles, but it&#8217;s to improve the query results, nothing more. I don&#8217;t see any IDs or sth. Just from where to where you are going and what method was successful for your query) I saw that a lot of requests for simple station names had to be handled by the &#8220;Google Fallback&#8221; &#8211; which is obviously not intended. This &#8220;Google Fallback&#8221; should catch up, when/if you search for an address or a POI (like Subway Restaurant Zurich). Why is that? Because the city mapping from Swiss Postal Service and SBB are quite different. I.e. there is a &#8220;Klein-Basel&#8221; in their database, where there is only a &#8220;Basel&#8221; on the SBB side.  Then there are various ambiguous names, like &#8220;Bern / Liebefeld&#8221; which is also no hit on SBB.ch .. I guess you see the point.</p>
<p>Summary: Google returns list a stations which do not have the same name on SBB.ch which cannot alway be corrected because the reverse geocoder is not always &#8220;right&#8221;.</p>
<p>What do you do in your darkest hours? Yes, you ask your friends. There are friends. I&#8217;d call them &#8220;GottaGo&#8221;&#8216;s Baywatch ;) I was looking for a solution. Since we plan to release the next iteration very soon and we need a lot of work to do. (Btw.: we is me and <a href="http://sichr.com">Stefan Sicher from sichr.com</a> who is working on the new design like a crazy cow ;) &#8211; and no, that design from the last blogpost is not from him, that&#8217;s just a mock-design I used to illustrate the layout)</p>
<p>Again &#8211; solution. I asked the guys over at <a href="http://local.ch">local.ch</a> again to help me out. Guess what &#8211; they did. They didn&#8217;t even say &#8220;Yes, we will look into it&#8221; &#8211; no. Just &#8220;Yes, we do it. Just say what you need so I can do it _before_ holidays&#8221;. Really &#8211; how awesome is this? This will require a few more Horsepower to be squeezed out of my dear &#8220;<a href="http://marc.freeflux.net/blog/archive/2007/04/13/real-man-s-toys.html">gonzo</a>&#8221; but it&#8217;s a real breath of fresh air &#8211; the light at the end of the tunnel ;)</p>
<p>So you might wonder, what they will provide me.. A lot. First of all: Station-names as on SBB.ch (really exactly the same) together with coordinates (<a href="http://en.wikipedia.org/wiki/WGS84">WGS</a> coordinates, they used <a href="http://en.wikipedia.org/wiki/Swiss_coordinate_system">CH1903</a> so far). Together with their superfast services and customized XML interface, this will free us from bloated information we don&#8217;t really need and exact information we really need.</p>
<p>Then there is autocomplete. I was really worried about that.. (Really really worried. I set this up on another server so I could do it with a different IP-Address in case SBB.ch would block this). I got full permission and a customized API to do autocomplete stuff on <a href="http://local.ch">local.ch</a> .. Again: superfast! (I know, SBB.ch does a lot more computing for that stuff, but it was really slow :))</p>
<p>As I read these lines, I wanted to tell Joel to bake a big cake so I could give it to the local team. For all those who asked me to open a Paypal account for donations or sth: abandon <a href="http://endoftheinternet.com">search.ch</a> and use <a href="http://local.ch">local.ch</a> from now on! ;) that would result in a win &#8211; win situation for all of us :)</p>
<p>Again: I just want to thank you <a href="http://blog.local.ch/">guys over at local.ch</a>, namely Vasile, Patrice, Ebi and Joel for your effort. I hope the users will appreciate it as much as I do :)</p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2008/08/22/there-are-friends-and-there-are-friends.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Whatever will be, will be..</title>
		<link>http://codesofa.com/blog/archive/2008/08/11/whatever-will-be-will-be.html</link>
		<comments>http://codesofa.com/blog/archive/2008/08/11/whatever-will-be-will-be.html#comments</comments>
		<pubDate>Mon, 11 Aug 2008 02:08:58 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[Information]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[0.0.2]]></category>
		<category><![CDATA[appstore]]></category>
		<category><![CDATA[GottaGo]]></category>
		<category><![CDATA[next-release]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://lab.codesofa.com/blog/archive/2008/08/11/whatever-will-be-will-be.html</guid>
		<description><![CDATA[Well.. Since you folks are really into changes these days, I&#8217;ll provide you with a little sneak-preview of what&#8217;s coming in the v0.1.0 &#8211; Annapurna release.   First off: Language support. GottaGo will be available in english, german, french and italian. And as you see: A totally new UI. (The green disappeared! ;))     [...]]]></description>
			<content:encoded><![CDATA[<p>Well.. Since you folks are really into changes these days, I&#8217;ll provide you with a little sneak-preview of what&#8217;s coming in the v0.1.0 &#8211; Annapurna release.</p>
<p style="clear:both;"> </p>
<p><img class="rightFloated" src="/files/00000031.png" alt="" width="200" height="384" />First off: Language support. GottaGo will be available in english, german, french and italian. And as you see: A totally new UI. (The green disappeared! ;))</p>
<p> </p>
<p style="clear:both;"> </p>
<p><img class="rightFloated" style="clear: left;" src="/files/2008-08-11_0346.png" alt="" width="200" height="384" /> <img class="rightFloated" src="/files/2008-08-11_0347.png" alt="" width="200" height="384" />Then we have had one request to include Cabs.. Well, since I don&#8217;t want to waste my time on cars, I asked the guys over at local to help me a bit here. Thanks to the help of <a href="http://gorn.ch">Tobias Ebnöther</a> and <a href="http://www.lejoe.com/blog/">Joel Bez</a> of the local.ch team at Liip, this works like a charm.</p>
<p> </p>
<p style="clear:both;"> </p>
<p><img class="rightFloated" style="clear: both;" src="/files/2008-08-11_0343.png" alt="" width="200" height="384" />And last but certainly not least, we have autocompletion. That&#8217;s the reason why the UI changed so much..</p>
<p style="clear:both;"> <br />
These are just the most significant changes. There are way more changes that you will notice. (Like track number.. But there will be _no_ track number for Zurich HB since this information is not available to me. (Try it on sbb.ch).</p>
<p>However, I cannot tell you about the exact release date. I&#8217;m having some exams the next two weeks, so I won&#8217;t have time to work a lot on this, but since I canceled release 0.0.2 (Dhaulagiri), this one might come around that time..</p>
<p>I want to thank you all out there for giving me many flowers and a few complaints. Makes working on this a little easier :)</p>
<p>The last few days, I&#8217;ve been browsing through the AppStore and I think it&#8217;s pretty cool, that 2 of the top 3 apps are not games in Switzerland. And as of the time of writing, neither is the number 1 app. In a lot of other AppStores, the games lead the rankings :) This might also change in the swiss AppStore in a few hours, but it&#8217;s cool that it takes a while..</p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2008/08/11/whatever-will-be-will-be.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A short note on CLLocation / CLLocationManager</title>
		<link>http://codesofa.com/blog/archive/2008/07/25/a-short-note-on-cllocation-cllocationmanager.html</link>
		<comments>http://codesofa.com/blog/archive/2008/07/25/a-short-note-on-cllocation-cllocationmanager.html#comments</comments>
		<pubDate>Thu, 24 Jul 2008 23:41:00 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[cllocation]]></category>
		<category><![CDATA[cllocationmanager]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://lab.codesofa.com/blog/archive/2008/07/25/a-short-note-on-cllocation-cllocationmanager.html</guid>
		<description><![CDATA[**** DEPRECATED **** Use http://liip.to/ilocator Well.. I&#8217;ve been testing this Locator quite a while now. Today I had my final attempt, to find out, why I always got either a cached location or an extremely inaccurate location. Today, I went out with my notebook (yes, there where the sun is..) to debug. The example of apple says, [...]]]></description>
			<content:encoded><![CDATA[<h3>**** DEPRECATED **** Use <a href="http://liip.to/ilocator">http://liip.to/ilocator</a></h3>
<p>Well.. I&#8217;ve been testing this Locator quite a while now. Today I had my final attempt, to find out, why I always got either a cached location or an extremely inaccurate location.</p>
<p>Today, I went out with my notebook (yes, there where the sun is..) to debug.</p>
<p>The example of apple says, to check the timestamp of the newLocation. (It should be less than 5..). Yeah well, guess what &#8211; it is sometimes 0 in a cached location. And somehow it&#8217;s sometimes just a bit over 5 and you&#8217;ll have to wait forever to get a new location.</p>
<pre><code>
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    NSDate* eventDate = newLocation.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];

    if (howRecent &lt; -0.0 &amp;&amp; howRecent &gt; -10.0) {
        [manager stopUpdatingLocation];

        // USE THE FORCE OF THE LOCATION!
    }
}
</code></pre>
<p>This one should work. Maybe that location stuff is working in the U.S. but it wasn&#8217;t in Switzerland..</p>
<p>P.S.: I had another issue with a pwned iPhone today. NSXMLParser throw me errors back and I didn&#8217;t know why.. I still don&#8217;t know why, I guess it had to do with the libxml2 update I did. Workaround? Restore, works fine now.</p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2008/07/25/a-short-note-on-cllocation-cllocationmanager.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Make NSXMLParser your friend..</title>
		<link>http://codesofa.com/blog/archive/2008/07/23/make-nsxmlparser-your-friend.html</link>
		<comments>http://codesofa.com/blog/archive/2008/07/23/make-nsxmlparser-your-friend.html#comments</comments>
		<pubDate>Wed, 23 Jul 2008 01:27:23 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[nsxml]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[recursive]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://lab.codesofa.com/blog/archive/2008/07/23/make-nsxmlparser-your-friend.html</guid>
		<description><![CDATA[Update: Since this is my most read blog article and it&#8217;s now 2 years old, one would think that things have changed, and they have. 2 Things: First, if you are free to choose between any API data representation, use JSON or plist, JSON is especially nice, because it&#8217;s very small and can be parsed [...]]]></description>
			<content:encoded><![CDATA[<h2>Update:</h2>
<p>Since this is my most read blog article and it&#8217;s now 2 years old, one would think that things have changed, and they have.<br />
2 Things: First, if you are free to choose between any API data representation, use JSON or plist, JSON is especially nice, because it&#8217;s very small and can be parsed with <a href="http://github.com/gabriel/yajl-objc">YAJL</a> or <a href="http://code.google.com/p/touchcode/wiki/TouchJSON">TouchJSON</a>.<br />
And second, and foremost, please use something less painful.. like <a href="http://code.google.com/p/wonderxml/">WonderXML</a> &#8211; it really really helps. However, if you are still up to using NSXMLParser &#8211; go on reading..</p>
<hr />
<p>For a demo on this, you may use <a href="http://svn.liip.ch/repos/public/iphone/MyBeer">http://svn.liip.ch/repos/public/iphone/MyBeer</a></p>
<p>As promised, here is a little How-I-did-it / How-To.</p>
<p>First off: I am not an experienced SAX-User.. So this approach might be packing the problem at it&#8217;s tail, but this is how DOM-Users feel comfortable with ;)</p>
<p>Let&#8217;s assume we want to parse the following XML:</p>
<h3 class="codetitle">tranist.xml</h3>
<pre><code class="prettyprint">&lt;root&gt;
    &lt;schedules&gt;
        &lt;schedule id="0"&gt;
            &lt;from&gt;SourceA&lt;/from&gt;
            &lt;to&gt;DestinationA&lt;/to&gt;
            &lt;links&gt;
                &lt;link id="0"&gt;
                    &lt;departure&gt;2008-01-01 01:01&lt;/departure&gt;
                    &lt;arrival&gt;2008-01-01 01:02&lt;/arrival&gt;
                    &lt;info&gt;With food&lt;/info&gt;
                    &lt;parts&gt;
                        &lt;part id="0"&gt;
                            &lt;departure&gt;2008-01-01 01:01&lt;/departure&gt;
                            &lt;arrival&gt;2008-01-01 01:02&lt;/arrival&gt;
                            &lt;vehicle&gt;Walk&lt;/vehicle&gt;
                        &lt;/part&gt;
                        &lt;part id="1"&gt;
                            &lt;departure&gt;2008-01-01 01:01&lt;/departure&gt;
                            &lt;arrival&gt;2008-01-01 01:02&lt;/arrival&gt;
                            &lt;trackfrom&gt;1&lt;/trackfrom&gt;
                            &lt;trackto&gt;2&lt;/trackto&gt;
                            &lt;vehicle&gt;Train&lt;/vehicle&gt;
                        &lt;/part&gt;
                    &lt;/parts&gt;
                &lt;/link&gt;
                &lt;link id="1"&gt;
                    ...
                &lt;/link&gt;
                &lt;link id="2"&gt;
                    ...
                &lt;/link&gt;
            &lt;/links&gt;
        &lt;/schedule&gt;
        &lt;schedule id="1"&gt;
            ...
        &lt;/schedule&gt;
        &lt;schedule id="2"&gt;
            ...
        &lt;/schedule&gt;
    &lt;/schedules&gt;
&lt;/root&gt;</code></pre>
<p>In human readable format, this means: We have multiple schedules with from/to etc. These schedules consist of multiple links (different connections for the same route) with departure/arrival etc. These links consist then of multiple parts/sections with various elements which are not sure to be there..</p>
<p>With the let&#8217;s find the element called &#8216;part&#8217; &#8211; approach, you won&#8217;t get anywhere..</p>
<h3>The Basics</h3>
<p>So what do we want to achieve? We want a list/array of Schedules, which have the given members. On member is a list/array of Links, also consisting of the given members and a list/array of parts with the respective members.</p>
<p>This is also the basic idea behind my approach: for every new node-container, use a new class/object (an array will also work, but it&#8217;s kinda crap..)</p>
<p>Now we have a Schedule class, a Link class and a Part class.</p>
<p>This is an example of the Link class interface:</p>
<h3 class="codetitle">Link.h</h3>
<pre><code class="prettyprint">#import "Part.h"

@interface Link : NSObject {
    NSString *departure;
    NSString *arrival;
    NSString *info;
    NSMutableArray *parts;
}

@property (nonatomic, retain) NSString *departure;
@property (nonatomic, retain) NSString *arrival;
@property (nonatomic, retain) NSString *info;
@property (readonly, retain) NSMutableArray *parts;

- (void)addPart:(Part *)part;

@end
</code></pre>
<p>We use an accessor method for the parts, because it just feels better when dealing with arrays. (Instead of later using [foo.myArray addObject:..] we have [foo addMe:..])</p>
<p>Also we make it easier for us, using retain properties..</p>
<h3>The Parser setup</h3>
<p>A short introduction into SAX:</p>
<p>The parsing goes node by node and is not nesting-sensitive. That means that first we get root, then schedules, then schedule, then from, then to, then links, then link, then departure etc. As soon as the parser returns you the  node for example, you don&#8217;t know anymore in what schedule you were. As long as you have a clearly defined structure where always every element must be present, you could do this using a counter, but as soon as you have multiple nodes with no defined count, you have a problem.</p>
<p>What we do is known as recursive parsing. What does this mean? We implement some kind of memory.</p>
<p>In our parser, we have 4 members and 1 method (to make actual use of the parser..):</p>
<pre><code class="prettyprint">@property (nonatomic, retain) NSMutableString *currentProperty;
@property (nonatomic, retain) Schedule *currentSchedule;
@property (nonatomic, retain) Link *currentLink;
@property (nonatomic, retain) Part *currentPart;
@property (nonatomic, readonly) NSMutableArray *schedules;

- (void)parseScheduleData:(NSData *)data parseError:(NSError **)error;
</code></pre>
<p>(Yes, this needs to be a NSMutableString..)</p>
<p>Your parseScheduleData method should look similar to the following:</p>
<h3 class="codetitle">parseJourneyData</h3>
<pre><code class="prettyprint">- (void)parseJourneyData:(NSData *)data parseError:(NSError **)err {
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

    self.schedules = [[NSMutableArray alloc] init]; // Create our scheduler list

    [parser setDelegate:self]; // The parser calls methods in this class
    [parser setShouldProcessNamespaces:NO]; // We don't care about namespaces
    [parser setShouldReportNamespacePrefixes:NO]; //
    [parser setShouldResolveExternalEntities:NO]; // We just want data, no other stuff

    [parser parse]; // Parse that data..

    if (err &amp;&amp; [parser parserError]) {
        *err = [parser parserError];
    }

    [parser release];
}
</code></pre>
<p>Now we need those delegate methods.</p>
<p>- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict</p>
<p>- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName</p>
<p>- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string</p>
<h4>- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string</h4>
<p>This function is called by the parser, when it reads something between nodes. (Text that is..) Like with blah it would read &#8220;blah&#8221;. It is possible, that this method is called multiple times in one node. As you will see later, we define the property &#8220;currentProperty&#8221; only if we find a node, we care about. That&#8217;s why we test it against this property to make sure, that we need this property. This will then look something like this:</p>
<h3 class="codetitle">Parser</h3>
<pre><code class="prettyprint">- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (self.currentProperty) {
        [currentProperty appendString:string];
    }
}
</code></pre>
<h4>- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict</h4>
<p>This is called, when the parser finds an opening element. In this case, we have a few cases, we need to distinguish. These are:</p>
<p>It&#8217;s standard property in the schedule (like &lt;form&gt; etc.) or it&#8217;s a deeper nested node (like &lt;links&gt;), the same for all the other nodes.</p>
<p>How to? We define, that we only set a member, if we are in that node. That means, only when we have entered a &lt;part&gt;, then currentPart is set, otherwise it&#8217;s nil. The same with the others.</p>
<p>We do then need to check them in reverse order of their nesting level.. Why? Because if we would check for currentLink before currentPart, currentLink would also evaluate to YES/True and hence we will have a problem if their are elements with the same name. If we aren&#8217;t in any node, then there is probably a new main node comming -&gt; in the else..</p>
<p>When we hit a nested node, we need to allocate the respective member of our class, so we can use it when the parser gets deeper into it.</p>
<p>This will look like this:</p>
<h3 class="codetitle">Parser</h3>
<pre><code class="prettyprint">- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if (qName) {
        elementName = qName;
    }

    if (self.currentPart) { // Are we in a
        // Check for standard nodes
        if ([elementName isEqualToString:@"departure"] || [elementName isEqualToString:@"arrival"] || [elementName isEqualToString:@"vehicle"] || [elementName isEqualToString:@"trackfrom"] || [elementName isEqualToString:@"trackto"] ) {
            self.currentProperty = [NSMutableString string];
        }
    } else if (self.currentLink) { // Are we in a
        // Check for standard nodes
        if ([elementName isEqualToString:@"departure"] || [elementName isEqualToString:@"arrival"] || [elementName isEqualToString:@"info"]) {
            self.currentProperty = [NSMutableString string];
        // Check for deeper nested node
        } else if ([elementName isEqualToString:@"part"]) {
            self.currentPart = [[Part alloc] init]; // Create the element
        }
    } else if (self.currentSchedule) { // Are we in a  ?
        // Check for standard nodes
        if ([elementName isEqualToString:@"from"] || [elementName isEqualToString:@"to"]) {
            self.currentProperty = [NSMutableString string];
        // Check for deeper nested node
        } else if ([elementName isEqualToString:@"link"]) {
            self.currentLink = [[Link alloc] init]; // Create the element
        }
    } else { // We are outside of everything, so we need a
        // Check for deeper nested node
        if ([elementName isEqualToString:@"schedule"]) {
            self.currentSchedule = [[Schedule alloc] init];
        }
    }
}
</code></pre>
<h4>- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName</h4>
<p>Basically, the same things apply as for didStartElement above. This time, we need to clean things up and assign them if they are set :) This is a bit a pitty, since it&#8217;s a lot of code.. *(for not so much)</p>
<p>It&#8217;s the same checker-structure..</p>
<p>If we are in a deeper nested node (like &lt;Link&gt;) and we hit an ending element of that nested node (like &lt;/Link&gt;), Then we need to add this element to the parent (like &lt;Schedule&gt;) and set it to nil</p>
<p>See yourself:</p>
<h3 class="codetitle">Parser</h3>
<pre><code class="prettyprint">- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if (qName) {
        elementName = qName;
    }

    if (self.currentPart) { // Are we in a
        // Check for standard nodes
        if ([elementName isEqualToString:@"departure"]) {
            self.currentPart.departure = self.currentProperty;
        } else if ([elementName isEqualToString:@"arrival"]) {
            self.currentPart.arrival = self.currentProperty;
        } else if ([elementName isEqualToString:@"vehicle"]) {
            self.currentPart.vehicle = self.currentProperty;
        } else if ([elementName isEqualToString:@"trackfrom"]) {
            self.currentPart.trackfrom = self.currentProperty;
        } else if ([elementName isEqualToString:@"trackto"]) {
            self.currentPart.trackto = self.currentProperty;
        // Are we at the end?
        } else if ([elementName isEqualToString:@"part"]) {
            [currentLink addPart:self.currentPart]; // Add to parent
            self.currentPart = nil; // Set nil
        }
    } else if (self.currentLink) { // Are we in a
        // Check for standard nodes
        if ([elementName isEqualToString:@"departure"]) {
            self.currentLink.departure = self.currentProperty;
        } else if ([elementName isEqualToString:@"arrival"]) {
            self.currentLink.arrival = self.currentProperty;
        } else if ([elementName isEqualToString:@"info"]) {
            self.currentLink.info = self.currentProperty;
        // Are we at the end?
        } else if ([elementName isEqualToString:@"link"]) {
            [currentSchedule addPart:self.currentLink]; // Add to parent
            self.currentLink = nil; // Set nil
        }
    } else if (self.currentSchedule) { // Are we in a  ?
        // Check for standard nodes
        if ([elementName isEqualToString:@"from"]) {
            self.currentSchedule.from = self.currentProperty;
        } else if ([elementName isEqualToString:@"to"]) {
            self.currentSchedule.to = self.currentProperty;
        // Are we at the end?
        } else if ([elementName isEqualToString:@"schedule"]) { // Corrected thanks to Muhammad Ishaq
             [schedules addObject:self.currentSchedule]; // Add to the result node
             self.currentSchedule = nil; // Set nil
        }
    }

    // We reset the currentProperty, for the next textnodes..
    self.currentProperty = nil;
}
</code></pre>
<h3>Finally..</h3>
<p>Well, that&#8217;s it. You can expand / shrink this principle as you like. You can also add a maxElements counter, like in the SeismicXML example of the iPhone SDK to get only a certain number of elements. You can abort the parser with [parser abortParsing]; It is important, that you don&#8217;t abort while in a deeper nested node, because this could lead to inconsistencies. You will need to skip them..</p>
<p>Please note, that I wrote this, while watching TV, so you may need to fix some syntax errors ;) But I hope you get the idea..</p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2008/07/23/make-nsxmlparser-your-friend.html/feed</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>And long nights follow field-days..</title>
		<link>http://codesofa.com/blog/archive/2008/07/21/and-long-nights-follow-field-days.html</link>
		<comments>http://codesofa.com/blog/archive/2008/07/21/and-long-nights-follow-field-days.html#comments</comments>
		<pubDate>Mon, 21 Jul 2008 06:58:27 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[fieldtesting]]></category>
		<category><![CDATA[GottaGo]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://lab.codesofa.com/blog/archive/2008/07/21/and-long-nights-follow-field-days.html</guid>
		<description><![CDATA[What a weekend. After I started with the real field-testing on Friday evening, it didn&#8217;t take me long to realize that I will need to fix a lot of issues :)  Since the girls are out of town, I had time for what I needed to do &#8211; refactoring. I had to modify the online [...]]]></description>
			<content:encoded><![CDATA[<p>What a weekend. After I started with the real field-testing on Friday evening, it didn&#8217;t take me long to realize that I will need to fix a lot of issues :)<br />
 Since the girls are out of town, I had time for what I needed to do &#8211; refactoring.</p>
<p>I had to modify the online service, since Google and SBB don&#8217;t always play nice together. Example? Hmm.. Google thinks, that there is a station named Rathaus, but SBB thinks, there are many many stations called Rathaus.. So I needed reverse geocoding for that. I did my own implementation with Google-Maps &#8211; but I cannot open it to anyone since they kinda don&#8217;t like that ;) I may publish the source though, I guess.</p>
<p>The next thing was, was to harden that thing &#8211; make it foolproof. Not an easy task, you say? Well, I gave it my grandfather for testing, he clicked things I would never click and that&#8217;s how I found a few more issues &#8211; I think this should be best practice ;)</p>
<p>Another thing I noted was that I fetch a ton of information I didn&#8217;t use.. like the vehicle and stuff. So the sections are now implemented as well.</p>
<p>So much about `software is done&#8217;</p>
<p>The reason why I made this entry at all is:<br />
&#8211; GottaGo is now ready for beta testing.. </p>
<p>That means I may invite 100 users to try out gottago without waiting for the AppStore release it.<br />
 </p>
<p><strong> What do I need/you need to do?</strong></p>
<p>You&#8217;ll need an iPhone. (first and second gen will work). iPod touch may also work, would be nice to have a tester.</p>
<p>I need your e-mail address &#8211; like in non-spam-e-mail address.<br />
Then I need your UDID/Device Id of your iPhone.. this is a tricky one :) Either you are an iPhone developer and you know how to find it or you can try the following:</p>
<ol>
<li>Connect your iWonderTouch with iTunes</li>
<li>In the Summary tab, click on the label &#8220;Serial Number&#8221; (yes, move your mouse over the &#8220;Serial Number&#8221; text and click!).</li>
<li>The &#8220;Serial Number&#8221; label should become &#8220;Identifier&#8221; and the ID should get longer ;)</li>
<li>You may screenshot this ID or type it into the e-mail by hand.. <strong>UPDATE: </strong>As Marc Liyanage noted in the comments: Just hit cmd-c after you see the identifier and paste it wherever you want it.. (thanks!) :)</li>
</ol>
<p>Should be it. Just send it to: m.m.ammann@gmail.com or leave a comment below. I will send you further instructions like our bugtracking system and stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2008/07/21/and-long-nights-follow-field-days.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>GottaGo &#8211; Why it&#8217;s not out there yet..</title>
		<link>http://codesofa.com/blog/archive/2008/07/17/gottago-why-it-s-not-out-there-yet.html</link>
		<comments>http://codesofa.com/blog/archive/2008/07/17/gottago-why-it-s-not-out-there-yet.html#comments</comments>
		<pubDate>Thu, 17 Jul 2008 01:22:14 +0000</pubDate>
		<dc:creator>marc</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[GottaGo]]></category>
		<category><![CDATA[libxml]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[sdk]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://lab.codesofa.com/blog/archive/2008/07/17/gottago-why-its-not-out-there-yet.html</guid>
		<description><![CDATA[Well, first of all, thanks for the great response on the first sneak preview of `GottaGo&#8217; &#8211; even though some people thought I&#8217;ve been on weed during the video presentation &#8211; I wasn&#8217;t :) It&#8217;s quite difficult to talk in presentation-loudness at 2am where I live.. So, what kept me from submitting to the AppStore? [...]]]></description>
			<content:encoded><![CDATA[<p>Well, first of all, thanks for the great response on the first sneak preview of `GottaGo&#8217; &#8211; even though some people thought I&#8217;ve been on weed during the video presentation &#8211; I wasn&#8217;t :) It&#8217;s quite difficult to talk in presentation-loudness at 2am where I live..</p>
<p>So, what kept me from submitting to the AppStore?<br />
Well, first of all I had to get my hands on a JesusPhone.. One I could work with. &#8211; Done -</p>
<p>You might say &#8211; there is a Simulator, the phone should be a small stage for the final testing. Yes, that&#8217;s what I thought.</p>
<p>Apparently, Apple allowed system libraries to be compiled into your software, while using the Simulator. Well &#8211; and since NSXMLDocument is not included in the final build of the SDK &#8211; I&#8217;m quite frankly &#8211; doomed now when I try to compile on the iPhone.</p>
<p>My options now are:</p>
<ul>
<li>libxml2 wrapper:
<ul>
<li>fix the iconara to work with iphone (linker errors)</li>
<li>write my own (jeeez)</li>
</ul>
</li>
</ul>
<ul>
<li>use plain libxml2:
<ul>
<li>spaghetti code</li>
<li>wheee</li>
</ul>
</li>
</ul>
<ul>
<li>use my own webservice to aggregate and send a small xml and parse via NSXMLParser (SAX):
<ul>
<li>sbb might block me for too many requests</li>
<li>bottleneck</li>
<li>yet another system that may fail</li>
</ul>
</li>
</ul>
<p>I think I&#8217;m going with the own webservice. It doesn&#8217;t feel right though. I think in a device that powerful, there should be a simple implementation of the DOM. I see the iPhone as a mobile device which should profit as much as possible from different webservices and cache only necessary things. Obviously Apple is more concerned about OpenGL(-Games) than about web-service access.</p>
<p>If there is a libxml wizard out there, feel free to contact me :)<br />
I&#8217;ll try to focus on libxml for some additional hours and if there is no hope, I&#8217;ll set up my own webservice. I hope I&#8217;ll be able to submit GottaGo to the AppStore this weekend.</p>
<p>And to clear some things up:</p>
<ul>
<li>GottaGo will be free of charge</li>
<li>GottaGo will only work in Switzerland for now</li>
</ul>
<p><strong>UPDATE</strong> Well.. After some hours of hacking, I was able to put GottaGo on my iPhone in a light-version. That means: location tracking and station finding, but no SBB querying for now. For SBB, I will probably have to proxy the requests since their response html is not even valid html.. But now there is some pressure on my shoulders. I was able to submit to AppStore. The requested release day is: July 19, so stay tuned :)</p>
<p><img src="/files/gottago/gottago_inreview.png" alt="" width="566" height="373" /></p>
]]></content:encoded>
			<wfw:commentRss>http://codesofa.com/blog/archive/2008/07/17/gottago-why-it-s-not-out-there-yet.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->