<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>tag:blog.danieljanus.pl,2019:category:iphone</id>
  <title>Daniel Janus – iPhone</title>
  <link href="http://blog.danieljanus.pl/category/iphone/"/>
  <updated>2012-09-13T00:00:00Z</updated>
  <author>
    <name>Daniel Janus</name>
    <uri>http://danieljanus.pl</uri>
    <email>dj@danieljanus.pl</email>
  </author>
  <entry>
    <id>tag:blog.danieljanus.pl,2012-09-13:post:my-top-three-ios-apps-for-mapping</id>
    <title>My top three iOS apps for mapping</title>
    <link href="http://blog.danieljanus.pl/my-top-three-ios-apps-for-mapping/"/>
    <updated>2012-09-13T00:00:00Z</updated>
    <content type="html">&lt;div&gt;&lt;p&gt;Living in London means that I now have a whole lot of new area to explore by cycling or walking. I try to take every opportunity to spend a free day or weekend out. One of the most important things when on the move is knowing where you are, where to go, and how to get there — and for that, you need a map. As I soon learned, the maps to use in the UK are the Ordnance Survey ones (either the Landranger/Explorer series, or maps by another publisher, such as AA, based on OS data). However, the Landranger series encompasses over 200 1:50000 maps, standing at some £8 each, and when that level of detail is not enough, there are more than 400 Explorer maps on top of that. Not only does this get pricey after a while, but also the sheer volume of map juggling quickly becomes impractical when you cycle a lot outside of town.&lt;/p&gt;&lt;p&gt;So I’ve turned to my old trusty iPhone 3GS as a mapping device instead, and set out to complete a set of mapping apps that do the job for me. In this post, I’d like to share my list.&lt;/p&gt;&lt;p&gt;I briefly thought of directly using OS maps on the iPhone via the &lt;a href="http://itunes.apple.com/gb/app/outdoors-gb-national-parks/id336150457?mt=8"&gt;Outdoors GPS GB app&lt;/a&gt;; it does meet my requirement of being accessible off-network, but the pricing of individual maps is on par with the paper version, so I ruled it out.&lt;/p&gt;&lt;p&gt;Instead, I am using this trio now:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;The official &lt;a href="http://itunes.apple.com/gb/app/the-complete-national-cycle/id436521445?mt=8&amp;amp;ls=1"&gt;National Cycle Network&lt;/a&gt; app by Sustrans. Beside being free, it has an advantage of detailing every numbered national cycle route, as well as most local routes (that often predate NCN or are not yet integrated into the network). At high detail, the data seem to be OS-sourced, which is good.&lt;br&gt;&lt;br&gt; It downloads maps from the Internet on demand, but you can also save a map portion for future use. The app asks you how much detail you want, tells you how large the download will be, then proceeds to get the data. The nuisance here is that you can only download 40 MB in one go, which corresponds to an area stretching for approximately 50-60 km at 1:50000 (and correspondingly smaller at 1:25000), so it takes a lot of tapping and downloading if you’re planning a longer trip.&lt;br&gt;&lt;br&gt; The other downsides are that the app is a little shaky at times, and GPS positioning sometimes displays your position somewhat misplaced. I mitigate this by using this app in combination with the next one…&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;…which is &lt;a href="http://www.mapswithme.com/"&gt;MapsWithMe&lt;/a&gt;. The tagline “Offline Mobile Maps” nails it down: it’s just maps, easily downloadable, covering the entire world, and nothing else. This really does one thing well. The map data source is OpenStreetMap, so all the maps are available for free as well; one ‘Download’ tap and you’ve got the whole country covered, once and for all. It also displays GPS position much more reliably than NCN. On the other hand, it can’t offer quite the same level of detail as NCN, and doesn’t know anything about cycle routes, but it’s still highly convenient.&lt;br&gt;&lt;br&gt; My typical flow when cycling in the UK is: check my position with MapsWithMe, then optionally switch to NCN, locate the same position on the map by hand and see where the route goes. I’ve also done one continental three-day trip, from Dunkirk in France to Hoek van Holland in the Netherlands, using just MapsWithMe to navigate, and it worked out very well.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Unlike the other two, the last app I want to point out, &lt;a href="http://www.codeartisans.co.uk/index.html"&gt;GPS2OS&lt;/a&gt;, is paid. And it’s more than worth its meager price, despite being next to useless when cycling. But when hiking, especially in remote mountainous areas, it can literally be a lifesaver. Here’s the catch: my basic navigation tools in harsh conditions are a compass and a plain ol’ paper map, and the iPhone is treated only as a supplementary aid (you never know when the battery goes out). However, instead of indicating the latitude and longitude in degrees/minutes/seconds, OS maps use &lt;a href="http://en.wikipedia.org/wiki/Ordnance_Survey_National_Grid"&gt;their own grid&lt;/a&gt;. So you cannot use the default Compass app, which tells you your position in degrees, directly with them, and you need a tool just like this one to do the coordinate translation. Works very well; it helped me find my way in dense mist down from the summit of Ben Macdui during my recent holiday in Scotland.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;One final tip: when you want to conserve battery as much as possible, airplane mode is a real saver. However, GPS doesn’t seem to work when airplane mode is on. So the next best thing is to remove the SIM card (you can then reinsert it, just don’t enter the PIN), so that the phone doesn’t keep trying to connect to cellular networks. And keep it warm in a pocket beside your body: cold devices discharge much faster.&lt;/p&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>tag:blog.danieljanus.pl,2011-07-08:post:meet-my-little-friend-createtree</id>
    <title>Meet my little friend createTree</title>
    <link href="http://blog.danieljanus.pl/meet-my-little-friend-createtree/"/>
    <updated>2011-07-08T00:00:00Z</updated>
    <content type="html">&lt;div&gt;&lt;p&gt;I’ve recently been developing an iPhone application in my spare time. I’m not going to tell you what it is just yet (I will post a separate entry once I manage to get it into the App Store); for now, let me just say that I’m writing it in JavaScript and HTML5, using [PhoneGap][1] and [jQTouch][2] to give it a native touch.&lt;/p&gt;&lt;p&gt;After having written some of code, I began testing it on a real device and encountered a nasty issue. It turned out that some of the screens of my app, containing a dynamically-generated content, sometimes would not show up. I tried to chase the problem down, but it seemed totally random. Finally, I googled up [this blog post][3] that gave me a clue.&lt;/p&gt;&lt;p&gt;My code was using jQuery’s &lt;code&gt;.html()&lt;/code&gt; method (and hence &lt;code&gt;innerHTML&lt;/code&gt; under the hood) to display the dynamic content. It turns out that, on Mobile Safari, using &lt;code&gt;innerHTML&lt;/code&gt; is highly unreliable (at least on iOS 4.3, but this seems to be a long-standing bug). Sometimes, the change just does not happen. I changed one of my screens, to build and insert DOM objects explicitly, and sure enough, it started to work predictably well.&lt;/p&gt;&lt;p&gt;So I had to remove all usages of &lt;code&gt;.html()&lt;/code&gt; from my app. The downside to it was that explicit DOM-building code is much more verbose than the version that constructs HTML and then sets it up. It’s tedious to write and contains much boilerplate.&lt;/p&gt;&lt;p&gt;To not be forced to change code, the above-quoted article advocates using a pure-JavaScript HTML parser outputting DOM to replace jQuery’s &lt;code&gt;.html()&lt;/code&gt; method. I considered this for a while, but finally decided against it — I didn’t want to include another big, complex dependency that potentially could misbehave at times (writing HTML parsers is &lt;em&gt;hard&lt;/em&gt;).&lt;/p&gt;&lt;p&gt;Instead, I came up with this:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createTree&lt;/span&gt;(&lt;span class="hljs-params"&gt;tree&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;typeof&lt;/span&gt; tree === &lt;span class="hljs-string"&gt;&amp;#x27;string&amp;#x27;&lt;/span&gt; || &lt;span class="hljs-keyword"&gt;typeof&lt;/span&gt; tree === &lt;span class="hljs-string"&gt;&amp;#x27;number&amp;#x27;&lt;/span&gt;)
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createTextNode&lt;/span&gt;(tree);
    &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; tag = tree[&lt;span class="hljs-number"&gt;0&lt;/span&gt;], attrs = tree[&lt;span class="hljs-number"&gt;1&lt;/span&gt;], res = &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createElement&lt;/span&gt;(tag);
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; attr &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; attrs) {
        val = attrs[attr];
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (attr === &lt;span class="hljs-string"&gt;&amp;#x27;class&amp;#x27;&lt;/span&gt;)
            res.&lt;span class="hljs-property"&gt;className&lt;/span&gt; = val;
        &lt;span class="hljs-keyword"&gt;else&lt;/span&gt;
            $(res).&lt;span class="hljs-title function_"&gt;attr&lt;/span&gt;(attr, val);
    }
     &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; i = &lt;span class="hljs-number"&gt;2&lt;/span&gt;; i &amp;lt; tree.&lt;span class="hljs-property"&gt;length&lt;/span&gt;; i++)
        res.&lt;span class="hljs-title function_"&gt;appendChild&lt;/span&gt;(&lt;span class="hljs-title function_"&gt;createTree&lt;/span&gt;(tree[i]));
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; res;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is very similar in spirit to &lt;code&gt;.html()&lt;/code&gt;, except that instead of passing HTML, you give it a data structure representing the DOM tree to construct. It can either be a string (which yields a text node), or a list consisting of the HTML tag name, an object mapping attributes to their values, and zero or more subtrees of the same form. Compare:&lt;/p&gt;&lt;p&gt;Using &lt;code&gt;.html()&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; html = &lt;span class="hljs-string"&gt;&amp;#x27;&amp;lt;p&amp;gt;This is an &amp;lt;span class=&amp;quot;red&amp;quot;&amp;gt;example.&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&amp;#x27;&lt;/span&gt;;
$(&lt;span class="hljs-string"&gt;&amp;#x27;#myDiv&amp;#x27;&lt;/span&gt;).&lt;span class="hljs-title function_"&gt;html&lt;/span&gt;(html);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using &lt;code&gt;createTree&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; tree = [&lt;span class="hljs-string"&gt;&amp;#x27;p&amp;#x27;&lt;/span&gt;, {},
            &lt;span class="hljs-string"&gt;&amp;#x27;This is an &amp;#x27;&lt;/span&gt;,
            [&lt;span class="hljs-string"&gt;&amp;#x27;span&amp;#x27;&lt;/span&gt;, {&lt;span class="hljs-string"&gt;&amp;#x27;class&amp;#x27;&lt;/span&gt;: &lt;span class="hljs-string"&gt;&amp;#x27;red&amp;#x27;&lt;/span&gt;}, &lt;span class="hljs-string"&gt;&amp;#x27;example.&amp;#x27;&lt;/span&gt;]];
$(&lt;span class="hljs-string"&gt;&amp;#x27;#myDiv&amp;#x27;&lt;/span&gt;).&lt;span class="hljs-title function_"&gt;empty&lt;/span&gt;().&lt;span class="hljs-title function_"&gt;append&lt;/span&gt;(&lt;span class="hljs-title function_"&gt;createTree&lt;/span&gt;(tree));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A side benefit is that it is just as easy to build up a tree dynamically as it is to create HTML, and the code often gets clearer. Note how the &lt;code&gt;createTree&lt;/code&gt; version above does not mix single and double quotes which is easy to mess up in the &lt;code&gt;.html()&lt;/code&gt; version.&lt;/p&gt;&lt;/div&gt;</content>
  </entry>
</feed>
