Florian GößleriOS-Expert with interest in Cloud Computing, Web Technologies & Product Management who loves new challenges - sharing some of my ideas, thoughts, experiences, tools and projects.
http://www.floriangoessler.de/
Sun, 19 Mar 2017 18:03:17 +0000Sun, 19 Mar 2017 18:03:17 +0000Jekyll v3.4.2Back from USA<p>The last 6 months were pretty exiting and I saw a lot of the USA but I’m very happy to be back in Germany.</p>
<p>I spent most of my time working at the BMW Tech Office in Mountain View. It was very interesting to see what challenges a global player like BMW faces and how they approach the digitalisation. I learned about the complexity of cars and especially about their entertainment system. About how a phone can interact with a BMW either in the car or via remote services. About the problems when working remotely on a big app and how the future might look like. I also learned a lot about the problems when developing for Apple Watch - you guess right it’s sometimes a real pain - and about how early stage the Swift compiler still is - compile times are not its best part yet :/.</p>
<p>I really liked the setting of the BMW Tech Office. It’s a small office with a very diverse team and a really great community. Not only did we interns see a lot California, Hawaii, Arizona and Vegas on our road trips, but also all the full time employees always have an open door for you. You can really learn a lot - also about other topics like autonomous driving, design or battery technologies - and have a lot of fun. They also never treat you like “a small intern” but you get real responsibilities and can actually have an impact on the projects.</p>
<p>However I’m happy to be back near my girlfriend, family and friends in a country with a (mostly) sane government, actual health care and affordable prices - food and housing is soooo cheap here xD. Also the weather is not that different right now - I just pretend for now that it continues to rain in California as it did while I was there ;-). I had a good time over there, hope to see all those awesome people again - some sooner some later - and really like to thank everyone who supported me on this trip.</p>
<p>So the next stations are called master thesis and ImmobilienScout in Berlin :-)</p>
Sun, 19 Mar 2017 19:10:00 +0000http://www.floriangoessler.de/uni/2017/03/19/Back-from-USA.html
http://www.floriangoessler.de/uni/2017/03/19/Back-from-USA.htmluniBack to JavaScript (and more)<p>This semester I was working together with a friend on a recommender system
for a small project at our university. They want to create a startup to
disrupt a still very old fashioned business by providing highly customized
recommendations for their users. During this project I was able to get my
hands back on JavaScript and see what changed in the ecosystem since I switched
to only native iOS development in 2014.</p>
<p>I won’t go into the details of the business here since they don’t matter
that much for this post.</p>
<h2 id="the-recommender">The Recommender</h2>
<p>We started our project with some research and talked with a lot of potential
clients to get to know their problems and evaluate whether we are on the
right track. We used a method called <a href="https://de.wikipedia.org/wiki/Problemzentriertes_Interview">problem centered interview</a>.</p>
<p>One challenge of the system is that we cannot use <a href="https://en.wikipedia.org/wiki/Collaborative_filtering">Collaborative Filtering</a>
because we neither have a large amount of existing user data nor do we
think that the domain is optimal for such recommendations. We are not
Amazon so we had to use something else.</p>
<p>We decided to go with a feature based approach. We generate a vector characterizing
the user’s preferences and also generate a vector for each item in our database.
Then we compare those vectors and rank all items based on the similarity
to the user vector. Using this method we can create a list of recommended
(and not recommended) items for each user.</p>
<p>The goal of our system is not only to present the best matches but also
to provide the user with some serendipitous options. To read more about
novel vs serendipitous see Chapter 3.4.2 of <a href="http://link.springer.com/chapter/10.1007%2F978-0-387-85820-3_3">this book</a>.</p>
<p>We also wanted to provide the user with a bundle of items and not with
the items alone.</p>
<h2 id="architecture">Architecture</h2>
<p>The systems we now constructed works like a pipeline:</p>
<p><img src="http://www.floriangoessler.de/images/back-to-javascript/pipeline.png" alt="Pipeline" class="scale-down-img center-image" /></p>
<p>We wanted to create a very modular system where each has a simple to use
<a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST API</a>.
This has a lot of advantages: Each component can be easily replaced, we can work platform independent,
scalable and the system easier to maintain.
The idea is to go into the direction of microservices from the start.
This might be an overkill for the project in it’s current state but we wanted to
try stuff out and get some experience - after all it’s a university project 😉.</p>
<p>Beside the existing user facing web prototype, which is build elsewhere,
we created 3 new components. To be honest we should split one of them in two or three
parts already to really satisfy the microservice definition and
single-responsibility principle.</p>
<ul>
<li>Part A: Reads data from the database (a Mongo DB) and creates
the user and feature vectors. This part also combines multiple items into a set (This should be it’s own service… 😬).</li>
<li>Part B: Computes the scores for the items.</li>
<li>Playground: A user interface to create user profiles to test the recommender.</li>
</ul>
<p>Via the exposed REST API it’s now hopefully easy to integrate this system
into the user facing web prototype.</p>
<h2 id="javascript-">JavaScript 😑</h2>
<p>I started with Part A in JavaScript while my friend was working on Part B
which is written in Python.</p>
<p>I thought that a JavaScript (JS) based server program running on node.js would be
nice since we are working with a mongo db, which was used by the user facing prototype,
and all models already had nice JSON representations. Beside this the frontend was written
in JS and I wanted to thee see how far node.js and JavaScript got since I last used it at
ImmobilienScout in early 2014.</p>
<p>I never really loved JS because its syntax is very verbose, has some odd twirks
and you can easily run into bugs that are hard to debug but caused by simple things.
It also completely lacks a static type system and a compiler which could guide you and
find a lot of errors. Therefore you need to be very careful to not break
things and a JS code base without a large and good set of unit tests is unmaintainable.
Of course you should use <a href="https://en.wikipedia.org/wiki/Test-driven_development">TDD</a>
for every project nowadays, but for JS and other script languages it’s way more important
than for compiled languages like Swift or Java.</p>
<p>JS has some advantages like a short deploy cycle and that it can now run
nearly everywhere (browsers, servers and even client apps). You can also
achieve some small things with not much effort and there a lot of good
open source libraries out there.</p>
<p>Back then at ImmobilienScout we used CoffeeScript, which can be compiled to JS. It
adds a lot of syntactic sugar and introduces concepts like classes which are otherwise
a bit strange to create. However it does not introduce a static type system.</p>
<p>So I started with node.js and CoffeeScript but soon realized that I miss
my good and strict type system with generics that I got used to in Swift.
So I had a look at Typescript!</p>
<h2 id="typescript-">Typescript! 😍</h2>
<p><a href="https://www.typescriptlang.org">Typescript</a> is a language driven by Microsoft but
completely Open Source. It’s goal is to make JavaScript more maintainable by adding a
type system and some other nice improvements. It compiles to JS and also supports all features
included in newer JavaScript version that you might not be able to use otherwise.</p>
<p>It’s still not as strict as some real binary compiled languages because
you can easily opt out of the typesystem if needed. E.g. when working with
a 3rd party library for which no type definitions exist.</p>
<p>So I started to migrate part A to TypeScript and it works really fine.
In combination with a set of unit tests you can mak changes fast and with
confidence not to break everything. Refactorings are way easier and the IDE
(WebStorm in my case) can help you a lot.</p>
<p>With TypeScript JavaScript starts to be a pleasure again 😉</p>
<h2 id="angular-2">Angular 2</h2>
<p>After creating the REST APIs we saw that we should have an easy way to
validate our recommendations and that we have to experiment a lot to optimize
the feature vectors and recommendation engine.</p>
<p>Therefore I built a small single-page interface which uses the existing
REST APIs. With it you can easily create a user profile and see the
generated recommendations.</p>
<p>I used Angular JS 1.x at ImmobilienScout and it made the life of a frontend developer
so much easier. Data-binding, dependency injection and all the other concepts that make
your app nicely structured and easy testable are very good.</p>
<p>Because of that <a href="https://angularjs.org">Angular JS</a> was my first choice when searching for
a frontend framework and since Angular 2 is in the release candidate phase it seemed stable
enough to give it a try and see what changed. The changes and improved abstractions are a
significant step forward. A nice thing is also that it’s built with TypeScript in mind and
uses a lot of the new ECMAScript features. It was easy to get into the concepts and to
write small components that follow the single responsibility principle.</p>
<p>The only two things that I have to critize is that the the <a href="https://github.com/angular/material2">Angular 2 Material Design library</a>
is still in very early stages and a lot of familiar controls and effects are missing.
The other thing that needs improvement is on how to get your app from dev stage to a real
production stage. I didn’t put much effort and research there since the playground interface
is not intended to be used by end users. But from what I saw it’s currently necessary to
perform several nontrivial steps to get your Angular 2 app into production mode.</p>
<h2 id="docker">Docker</h2>
<p>In the beginning we worked with a simple command line script setup to run all the parts on
our local machines (all macs). But at some point I didn’t want to fiddle around with python
versions, node installations and differing local configurations. We also wanted to be able
to deploy it easily to some cloud service. That’s when I got my hands on <a href="https://www.docker.com">Docker</a>.</p>
<p>I once had a little tutorial about Docker at university but a lot has changed since then!
You need some time to get into all the services and which tool to use for what task, but
in the end it makes your work significantly easier.</p>
<p>One rule that I discovered to late or thought that it is just overhead is: One container per service.
If you have a node.js app and a database put them in different, dedicated containers!
Then use Docker Compose to bundle all services of your system together. This makes configuration
and management much easier. You can then deploy your whole system with just one command -
which is great to onboard developers and be able to try out any part of the system before
knowing how it exactly works.</p>
<p>After I had Docker running locally I wanted to deploy the whole system on a simple machine
in the cloud. No complex scalability or distribution. Surprisingly that’s not that easy if
you try to start with the advertisement pages for Amazons Container Service 🙄. It includes and
builds upon publishing your Docker images to a repository and a lot of configuration.
That’s certainly great for a system on production scale for a larger company but not to
just try stuff out 😝</p>
<p>Fortunately Docker has some nice guides on their own homepage to deploy a Docker Compose setup via Docker Machine
on AWS and Digital Ocean. I found Digital Ocean to be easier and now have an instance of my
system (consisting of 3 docker images combined via docker-compose) deployed in the cloud
on a Digital Ocean instance. 🎉</p>
<h2 id="outlook">Outlook</h2>
<p>I learned a lot during this project regarding recommender system, the node.js/JavaScript
ecosystem, Docker and cloud deployment. However there’s still a lot of work to do for the
recommender.</p>
<p>It needs to be integrated in the main frontend prototype - not that easy since there are
no unit tests yet :/ . We also need more data and items to improve the recommender and validate
our approach. There needs to be a systematic test for different user profiles.</p>
<p>Hopefully I have some time to continue the work in my spare time 😀</p>
Thu, 01 Sep 2016 10:00:00 +0000http://www.floriangoessler.de/uni/2016/09/01/Back-to-Javascript-and-more.html
http://www.floriangoessler.de/uni/2016/09/01/Back-to-Javascript-and-more.htmluniRecap and Off to New Shores<p>This spring and summer was very exiting and a lot is changing. My time
at ImmobilienScout 24 is ending and a new chapter begins next month when
I start to work for the BMW Technology Office in Mountain View, California.</p>
<p>I started to work at ImmobilienScout 24 in 2012 as a working student and
am now leaving after nearly 4 years. It’s been a great time and I really
learned a lot there.</p>
<p>I started as Scout 24 to maintain two hybrid apps which were written in Javascript
and it was a real “challenge” to get stuff done in there xD.
Fortunately I was then assigned to develop a mobile version of the real
estate financing portal and joined a team of experienced engineers. It
was nice to learn a lot about working in a professional, agile team and
the guys (and girls) were awesome in including me into really everything they did. I
never felt like “the little working student” but was part of the
team. I think this had a huge impact on me and I hope they continue to
operate on this high level!</p>
<p>Since I already had a lot of experience in developing native iOS apps and we
wanted to shut down the fragile and outdated hybrid apps, I joined the
iOS team to include the most important parts of those apps in the main
ImmobilienScout 24 iOS app.</p>
<p>At first it was experiment if this way of working would go well, since we
had to communicate between several departments with different business
goals. But it proved to be successful very soon and I was integrated into
the iOS team like a full member as well. In 2014 my working student
contract had to end because of a 2 year limit, but I was then hired under
a “normal” contract and continued to split my time between work and studying.</p>
<p>We built a lot of cool features and I was also able to push some code
modernization projects. It was very motivating to see the trust the team
had in me. Of course we had bugs, sometimes though deadlines or strange
requirements but that’s business and as long as the team faces these
challenges together it’s more fun than chore to get to work in the morning.
We had great product owners with love to details and UX, some very good
designers (although we had times were our resources were limited in that
field) and an awesome team of engineers in the iOS as well as the Android team.
After all I was more motivated to go to work than to university :-)</p>
<p>In 2015 I won a ticket for the WWDC and although it was some hazzle to get
the budget cleared for me because of some organizational things, I could
visit San Francisco together with a colleague. Big thanks to all those people who
helped to make this work! It was my first time in the US and
it was really awesome. I can only recommend everyone who’s interested in
iOS to get there at least once.</p>
<p>After my short visit to San Francisco I knew that I want to get there again.
Unfortunately my first attempts to apply for a job or internship at several
companies didn’t went well. After all it’s risky for those companies to get
people form europe. But thanks to some fellow students I got to know about
the BMW Technology Office in Mountain View and applied there. It took a
while, but then in May I got the positive response.</p>
<p>Now after all the bureaucratic burdens I finally have my J-1 Visa and am
heading of to the states tomorrow. It’s not an easy leave since I need to
leave a lot behind - at least until christmas. But it’s also very exiting
and I hope to see and learn a lot over there in the next 6 months. After
that I’ll come back in March, write my master’s thesis and then we will
see. :-)</p>
<p>Thanks to all those people who supported me during my time at
ImmobilienScout 24! It was a pleasure to work with you and keep
motivating and educating young software engineers.</p>
<p><br /><br /><br />
<em>PS: I didn’t include names here on purpose, because I don’t know who
wants to be named. I guess everyone knows when he or she is mentioned
indirectly ;-)</em></p>
Tue, 30 Aug 2016 07:28:00 +0000http://www.floriangoessler.de/ios/2016/08/30/Recap-and-Off-to-New-Shores.html
http://www.floriangoessler.de/ios/2016/08/30/Recap-and-Off-to-New-Shores.htmliosSwift Service Locator<p>As already mentioned in my <a href="/ios/2015/08/22/Swift-Dependency-Injection.html">previous post about Dependency Injection in Swift</a> I think that DI is essential for a maintainable and testable code base. I wasn’t completely happy with my previous solutions cause you had to write a lot of boilerplate code and explicit methods. <a href="https://twitter.com/eikemeier">Oliver Eikemeier</a> gave some nice talks at the <a href="http://cocoaheads-berlin.org">Cocoaheads</a> and <a href="http://swift.berlin">Swift.berlin</a> meetups in Berlin last year about modularization and architecture of apps including a way better solution for DI, that I adapted to my needs and want to share with you here.</p>
<p>It would be nice if we had just one <code class="highlighter-rouge">inject()</code> method on a central <code class="highlighter-rouge">ServiceLocator</code> and Swift would infer which object it should return via type inference and a configuration table inside the <code class="highlighter-rouge">ServiceLocator</code>, which can be configured with simple <code class="highlighter-rouge">register()</code> calls.</p>
<p>Swift 2.0 introduced the new <code class="highlighter-rouge">ObjectIdentifier</code> struct with which we get something hashable from a plain type in Swift. We can use
this as a key in a dictionary now. That’s just the part that I didn’t find when I wrote my last post!</p>
<p>So how does this new <code class="highlighter-rouge">ServiceLocator</code> look like?</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">class</span> <span class="kt">ServiceLocator</span> <span class="p">{</span>
<span class="kd">private</span> <span class="k">var</span> <span class="nv">registry</span> <span class="o">=</span> <span class="p">[</span><span class="kt">ObjectIdentifier</span><span class="p">:</span><span class="kt">Any</span><span class="p">]()</span>
<span class="kd">static</span> <span class="k">var</span> <span class="nv">sharedLocator</span> <span class="o">=</span> <span class="kt">ServiceLocator</span><span class="p">()</span>
<span class="c1">// MARK: Registration</span>
<span class="kd">func</span> <span class="n">register</span><span class="o">&lt;</span><span class="kt">Service</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">factory</span><span class="p">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">serviceId</span> <span class="o">=</span> <span class="kt">ObjectIdentifier</span><span class="p">(</span><span class="kt">Service</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
<span class="n">registry</span><span class="p">[</span><span class="n">serviceId</span><span class="p">]</span> <span class="o">=</span> <span class="n">factory</span>
<span class="p">}</span>
<span class="kd">static</span> <span class="kd">func</span> <span class="n">register</span><span class="o">&lt;</span><span class="kt">Service</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">factory</span><span class="p">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span><span class="p">)</span> <span class="p">{</span>
<span class="n">sharedLocator</span><span class="o">.</span><span class="nf">register</span><span class="p">(</span><span class="n">factory</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">// MARK: Injection</span>
<span class="kd">static</span> <span class="kd">func</span> <span class="n">inject</span><span class="o">&lt;</span><span class="kt">Service</span><span class="o">&gt;</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">sharedLocator</span><span class="o">.</span><span class="nf">inject</span><span class="p">()</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="n">inject</span><span class="o">&lt;</span><span class="kt">Service</span><span class="o">&gt;</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">serviceId</span> <span class="o">=</span> <span class="kt">ObjectIdentifier</span><span class="p">(</span><span class="kt">Service</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">factory</span> <span class="o">=</span> <span class="n">registry</span><span class="p">[</span><span class="n">serviceId</span><span class="p">]</span> <span class="nf">as</span><span class="p">?</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span> <span class="p">{</span>
<span class="k">return</span> <span class="nf">factory</span><span class="p">()</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nf">fatalError</span><span class="p">(</span><span class="s">"No registered entry for </span><span class="se">\(</span><span class="kt">Service</span><span class="o">.</span><span class="k">self</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>You can now register a service and inject it like this:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kt">ServiceLocator</span><span class="o">.</span><span class="n">register</span> <span class="p">{</span> <span class="kt">MyService</span><span class="p">()</span> <span class="p">}</span>
<span class="k">let</span> <span class="nv">myService</span><span class="p">:</span> <span class="kt">MyService</span> <span class="o">=</span> <span class="kt">ServiceLocator</span><span class="o">.</span><span class="nf">inject</span><span class="p">()</span></code></pre></figure>
<p>It’s important to consider that the <code class="highlighter-rouge">ObjectIdentifier</code> is very specific. This means if you want to register implementations of a certain protocol you need to cast your implementation instance to that protocol during registration:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kt">ServiceLocator</span><span class="o">.</span><span class="n">register</span> <span class="p">{</span> <span class="kt">MyServiceImpl</span><span class="p">()</span> <span class="k">as</span> <span class="kt">MyServiceProtocol</span> <span class="p">}</span>
<span class="k">let</span> <span class="nv">myService</span><span class="p">:</span> <span class="kt">MyServiceProtocol</span> <span class="o">=</span> <span class="kt">ServiceLocator</span><span class="o">.</span><span class="nf">inject</span><span class="p">()</span></code></pre></figure>
<p>Also optionals and implicit unwrapped optionals create another <code class="highlighter-rouge">ObjectIdentifier</code> than the plain types. Therefore I recommend to avoid optionals and implicit unwrapped optionals in the <code class="highlighter-rouge">ServiceLocator</code> so that you only register and inject “clean” types.</p>
<p>You can extended the <code class="highlighter-rouge">ServiceLocator</code> by a <code class="highlighter-rouge">registerSingleton(singletonInstance: Service)</code> method to avoid the typical <code class="highlighter-rouge">sharedInstance()</code> implementations and make it more explicit which objects will be recreated for every <code class="highlighter-rouge">inject()</code> call and for which you will always get the same:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">func</span> <span class="n">registerSingleton</span><span class="o">&lt;</span><span class="kt">Service</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">singletonInstance</span><span class="p">:</span> <span class="kt">Service</span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">serviceId</span> <span class="o">=</span> <span class="kt">ObjectIdentifier</span><span class="p">(</span><span class="kt">Service</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
<span class="n">registry</span><span class="p">[</span><span class="n">serviceId</span><span class="p">]</span> <span class="o">=</span> <span class="n">singletonInstance</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="n">inject</span><span class="o">&lt;</span><span class="kt">Service</span><span class="o">&gt;</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">serviceId</span> <span class="o">=</span> <span class="kt">ObjectIdentifier</span><span class="p">(</span><span class="kt">Service</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">factory</span> <span class="o">=</span> <span class="n">registry</span><span class="p">[</span><span class="n">serviceId</span><span class="p">]</span> <span class="nf">as</span><span class="p">?</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Service</span> <span class="p">{</span>
<span class="k">return</span> <span class="nf">factory</span><span class="p">()</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="k">let</span> <span class="nv">singletonInstance</span> <span class="o">=</span> <span class="n">registry</span><span class="p">[</span><span class="n">serviceId</span><span class="p">]</span> <span class="k">as?</span> <span class="kt">Service</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">singletonInstance</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nf">fatalError</span><span class="p">(</span><span class="s">"No registered entry for </span><span class="se">\(</span><span class="kt">Service</span><span class="o">.</span><span class="k">self</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Of course you need one point where you register all your services at the <code class="highlighter-rouge">ServiceLocator</code>. One good point would be the <code class="highlighter-rouge">AppDelegate</code>, but this can become a bit tedious if you have a large app. Therefore I’m using modules for each part of my app and only register these modules with the <code class="highlighter-rouge">ServiceLocator</code> in the <code class="highlighter-rouge">AppDelegate</code>. This helps to keep domain logic close together, improves modularization and makes your app scalable.</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">protocol</span> <span class="kt">ServiceLocatorModul</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">registerServices</span><span class="p">(</span><span class="nv">serviceLocator</span><span class="p">:</span> <span class="kt">ServiceLocator</span><span class="p">)</span>
<span class="p">}</span>
<span class="kd">extension</span> <span class="kt">ServiceLocator</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">registerModules</span><span class="p">(</span><span class="nv">modules</span><span class="p">:</span> <span class="p">[</span><span class="kt">ServiceLocatorModul</span><span class="p">])</span> <span class="p">{</span>
<span class="n">modules</span><span class="o">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="nf">registerServices</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="kt">MyModul</span><span class="p">:</span> <span class="kt">ServiceLocatorModul</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">registerServices</span><span class="p">(</span><span class="nv">serviceLocator</span><span class="p">:</span> <span class="kt">ServiceLocator</span><span class="p">)</span> <span class="p">{</span>
<span class="n">serviceLocator</span><span class="o">.</span><span class="n">register</span> <span class="p">{</span> <span class="kt">MyService</span><span class="p">()</span> <span class="p">}</span>
<span class="o">...</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Though, you need to be a bit careful in which order you register the dependencies and what depends on what: There’s no solution for cyclic dependencies here!</p>
<p>In unit tests you can easily register your mock implementations for injection. It’s also recommended to wipe the registry of the <code class="highlighter-rouge">ServiceLocator</code> before every test to ensure a clean state and avoid injection of real implementations by accident.</p>
<p>You can find my default <code class="highlighter-rouge">ServiceLocator</code> including a <code class="highlighter-rouge">CocoaDefaultModul</code>, which includes some basic iOS singletons, in this <a href="https://gist.github.com/FGoessler/2b7df61ab3fb81048de3">Gist</a>.</p>
<p>Of course there’s a lot of things you could add to such a <code class="highlighter-rouge">ServiceLocator</code>:</p>
<ul>
<li>Check that it’s only used in initializers - Oliver did that.</li>
<li>Add identifier strings to use multiple different registrations for one type - like Spring in Java does with @Qualifier annotations.</li>
<li>Use multiple <code class="highlighter-rouge">ServiceLocator</code> instances in your app. Each one for a specific part. You might want to drop the <code class="highlighter-rouge">sharedLocator</code> then and pass specific locators around.</li>
</ul>
<p>Because of all this variants, differing personal preferences and it’s actual simplicity I won’t make a pod/lib out of this and leave it as an exercise to the reader to copy the parts you like for your project ;-).</p>
<p>Thanks again @ <a href="https://twitter.com/eikemeier">Oliver</a> for his talks and his implementation of a <code class="highlighter-rouge">ServiceLocator</code>, which I just modified to my needs here. You can find that in his <a href="https://github.com/zalando/ModularDemo">demo project</a> - it’s called <a href="https://github.com/zalando/ModularDemo/blob/master/ZContainer/ZContainer/ZContainer.swift">ZContainer</a> there.</p>
Sun, 24 Jan 2016 22:49:00 +0000http://www.floriangoessler.de/ios/2016/01/24/Swift-Service-Locator.html
http://www.floriangoessler.de/ios/2016/01/24/Swift-Service-Locator.htmliosIBOutlets Should Be Optional<p>If you drag an IBOutlet from a XIB or storyboard to your Swift file, XCode will generate an implicitly unwrapped optional by default.</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">@IBOutlet</span> <span class="k">weak</span> <span class="k">var</span> <span class="nv">label</span><span class="p">:</span> <span class="kt">UILabel</span><span class="o">!</span></code></pre></figure>
<p>At first you might think that’s totally OK. Those properties won’t be set in the initializer, but when the view loads. And since you’re usually not doing much with your view controller until it has a view nothing breaks.</p>
<p>And then you add handling of memory warnings and suddenly you get crashes!</p>
<p>Why that?</p>
<p>Consider the following very simple view controller:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">class</span> <span class="kt">ChristmasViewController</span><span class="p">:</span> <span class="kt">UIViewController</span> <span class="p">{</span>
<span class="kd">@IBOutlet</span> <span class="k">weak</span> <span class="k">var</span> <span class="nv">label</span><span class="p">:</span> <span class="kt">UILabel</span><span class="o">!</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">didReceiveMemoryWarning</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="o">.</span><span class="nf">didReceiveMemoryWarning</span><span class="p">()</span>
<span class="k">if</span> <span class="nf">isViewLoaded</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">view</span><span class="o">.</span><span class="n">window</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
<span class="n">view</span> <span class="o">=</span> <span class="kc">nil</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">viewDidLoad</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="o">.</span><span class="nf">viewDidLoad</span><span class="p">()</span>
<span class="n">label</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"Happy Holidays!"</span>
<span class="p">}</span>
<span class="c1">/// This method might be called at any time from other classes!</span>
<span class="kd">func</span> <span class="nf">updateWithExternalString</span><span class="p">(</span><span class="nv">str</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="p">{</span>
<span class="n">label</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">str</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>As you can see the view is unloaded in case of a memory warning, since it can be recreated easily. Unfortunately there are other parts of the view controller that assume that the outlets are never nil - they are implicitly unwrapped so it’s not that obvious to the user of those properties or callers of public methods!</p>
<p>Similar things can happen if you use KVO or NSNotifications, which might be fired while your view is not present. Of course you can (and should!) also handle these cases by unregistering those observers when discarding the view.</p>
<p>To solve this problem, we as a team agreed on making those optionals real optionals. They are optional after all so lets use the features that Swift gives us.</p>
<p>The view controller from above might now look something like this:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">class</span> <span class="kt">ChristmasViewController</span><span class="p">:</span> <span class="kt">UIViewController</span> <span class="p">{</span>
<span class="kd">@IBOutlet</span> <span class="k">weak</span> <span class="k">var</span> <span class="nv">label</span><span class="p">:</span> <span class="kt">UILabel</span><span class="p">?</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">didReceiveMemoryWarning</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="o">.</span><span class="nf">didReceiveMemoryWarning</span><span class="p">()</span>
<span class="k">if</span> <span class="nf">isViewLoaded</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">view</span><span class="o">.</span><span class="n">window</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
<span class="n">view</span> <span class="o">=</span> <span class="kc">nil</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">viewDidLoad</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="o">.</span><span class="nf">viewDidLoad</span><span class="p">()</span>
<span class="k">guard</span> <span class="k">let</span> <span class="nv">label</span> <span class="o">=</span> <span class="n">label</span>
<span class="k">else</span> <span class="p">{</span><span class="nf">fatalError</span><span class="p">(</span><span class="s">"Outlets not correctly initialized!"</span><span class="p">)}</span>
<span class="n">label</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"Happy Holidays!"</span>
<span class="p">}</span>
<span class="c1">/// This method might be called at any time from other classes!</span>
<span class="kd">func</span> <span class="nf">updateWithExternalString</span><span class="p">(</span><span class="nv">str</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="p">{</span>
<span class="n">label</span><span class="p">?</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">str</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Of course this adds guard statements and other checks but makes the semantic more obvious and clear. Also we now get better error messages in case something crashes. If we screwed up some outlet we get a message telling us exactly this.</p>
<p>In general I would recommend to avoid implicitly unwrapped optionals whenever possible. Sometimes they seem convenient, but there’s usually a more explicit and safer way of doing it!</p>
Wed, 23 Dec 2015 11:44:00 +0000http://www.floriangoessler.de/ios/2015/12/23/IBOutlets-Should-Be-Optional.html
http://www.floriangoessler.de/ios/2015/12/23/IBOutlets-Should-Be-Optional.htmliosThoughts on Open Source Swift<p>So <a href="https://swift.org">Swift</a> is finally <a href="https://github.com/apple/swift">open sourced</a> and we are seeing some very interesting things in there!</p>
<h2 id="whats-in-there">What’s in there</h2>
<p>First of all there’s the runtime and stdlib in the open source part - as we probably all expected. But they also reimplemented Foundation and XCTest, which is important for cross-platform portability cause otherwise you couldn’t use all the NS* classes - which will also loose their prefix in the nearer future btw!</p>
<p>Linux Support is there from the start and will be maintained by Apple beside OS X and iOS and all it’s spin-offs. There are already people working on <a href="https://github.com/apple/swift/pull/203">FreeBSD support</a> and I think also Windows will come eventually from people in the community since LLVM and clang are already ported to Windows.</p>
<p>The two things I’m exited about the most is the <strong>public</strong> <a href="https://github.com/apple/swift-evolution">Swift 3.0 Roadmap</a> and the <a href="https://github.com/apple/swift-package-manager">Swift Package Manager</a>. Would be great if we get a fully integrated alternative to CocoaPods - which is great but has its problems.</p>
<h2 id="perspectives-for-the-future">Perspectives for the future</h2>
<p>So where is all this heading?</p>
<p>I think we’ll start writing server code in Swift for our apps pretty soon. There are already a bunch of prepacked Swift Docker containers out there and people are already playing with it. But to get it ready for production usage we also need great frameworks for the server side. Having a Java Spring MVC background, I think we need something similar to Spring. The framework needs to be powerful and should reduce boilerplate code so that you can focus on writing your application code and all the nasty request handling, queuing, threading, JSON/XML (de)serialisation, header handling, security, authentication and authorisation stuff is done for you and you only need to configure it.</p>
<p>For that we also need frameworks to access all sorts of databases and cloud resources as well. We need a very good AWS Server Side SDK in Swift and it would be awesome if <a href="https://aws.amazon.com/de/lambda/">AWS Lambda</a> would support Swift as well. At the moment we could maybe do something like <a href="http://blog.0x82.com/2014/11/24/aws-lambda-functions-in-go/">this guy proposed for GO</a>.</p>
<p>We also need a really good (free?) IDE for Swift on other platforms - maybe written in Swift ;-). Otherwise we’ll still constrain the language to people who have Apple Hardware. Maybe JetBrains could expand their <a href="https://www.jetbrains.com/objc/">AppCode IDE</a>?</p>
<p>If we as a community manage to build all that great stuff - and I think we’ll manage that - Swift has a great future on the server side. Swift might even pressure Java, Python and Scala.</p>
<p>We probably cannot “convert” all those “script kiddies” who love Python and Javascript with their unsafe and dynamically typed concept. But Swift has the great advantage over Java that it’s less verbose, more clear and shorter. It is easier than Scala, which is pretty powerful but also sometimes just unreadable and you don’t know what the code is doing if you haven’t mastered every aspect of Scala yet. Also Swift wasn’t born as some academic language to try something. It was developed to make programming and especially iOS App programming easier and available for more people. Because of that I hope that a lot more students will learn Swift as their first programming language.</p>
<p>But there are also some things in the language that I still miss. There’s no real way of meta programming which blocks things like powerful dependency injection and mocking frameworks. I’m not asking for a dynamic system with reflection like in Java, but I think about a concept of custom annotations (similar to IBOutlet) which inject some developer defined code or behaviour on compile time. I don’t have a real finalized concept and I’m also sceptical if it aligns with the goals of simplicity and clearness of Swift.</p>
<p>Open sourcing Swift is a great milestone and now it’s up to us as a community to make the best out of it and support those guys at Apple. They probably had a hard time to get all the permissions to open source it and to work on it in public on GitHub. Let’s honor that and become a great community.</p>
Sat, 05 Dec 2015 10:52:00 +0000http://www.floriangoessler.de/ios/2015/12/05/Thoughts-on-Open-Source-Swift.html
http://www.floriangoessler.de/ios/2015/12/05/Thoughts-on-Open-Source-Swift.htmliosAB Testing with Optimizely on iOS<p>AB testing is an important part of agile software product development and revenue optimization nowadays. <a href="https://optimizely.com">Optimizely</a> claims to have a poweful solution for iOS, which is especially nice when you’re already using it for the good old web and want to support Android. Let’s have a closer look!</p>
<p>I won’t go into what’s AB testing in detail. Have look at <a href="https://en.wikipedia.org/wiki/A/B_testing">wikipedia</a> or google it. Basically it’s just splitting your customers into groups, distributing a different version of your website/app to each group and you measuring which variant performs better for your goals (revenue, interactions, …).</p>
<h2 id="what-does-optimizely-for-ios-offer">What does Optimizely for iOS offer?</h2>
<p>With Optimizely you have a set of building blocks that you can use to compose your tests. You have ways to customize the variations, audience targeting possibilities and of course tracking of events and goals.</p>
<p>One nice thing of Optimizely, in comparsion to other AB testing tools like <a href="https://developer.amazon.com/appsandservices/apis/manage/ab-testing">Amazon AB Testing</a>, is that you can reuse your variation configuration options, goals, etc. for multiple tests. Of course it’s a problem if you run two tests at the same time with colliding configurations. E.g. test A wants the button to be red, but test B wants the button to be green. But Optimizely warns you about such conflicts.</p>
<p><br /></p>
<hr />
<p><br /></p>
<p>To configure variations Optimizely you need to install the Optimizely SDK in you app and start the “Editor Mode”. In this “Editor Mode” your device is connected with the web interface of Optimizely and you can see the changes that you make directly on your device and a preview in the web interface. You have 3 ways to configure a variation:</p>
<h4 id="1-ui-editor">1. UI Editor</h4>
<p>With the UI editor you can modify your UI, e.g. button placement and the text of labels. Even as a non technical person.
This is one of the larger features of Optimizely but also the one I, as a software engineer, don’t like and don’t trust at all.
If you’ve ever done complex layouting and know about the problems of autolayout on iOS, it’s hard to trust an “automated engine” and your non-engineering product owner to cover all possible variants and edge cases of layouting - especially in times of differently sized iPhones.
Luckily you can disable this feature with a simple boolean variable in your code ;-)</p>
<h4 id="2-live-variables">2. Live Variables</h4>
<p>With Live Variables you can configure remote variables. You define the value in the Optimizely web interface and the app uses that value at runtime.
In your iOS code you create a ‘placeholder’ with a default value. Optimizely registers this variable when you start the app in the “Editor Mode” and you can then use and configure it for your tests and variations. Back in your code you use the placeholder and the Optimizely SDK to get the current value for the user in respect to running AB tests on runtime.
You can use all sorts of types for your variable: Strings, Numbers, Bools, CGRect, UIColor, …</p>
<h4 id="3-code-blocks">3. Code Blocks</h4>
<p>With Code Blocks you can define different blocks of code (yes simple objective blocks or swift closures) in your iOS code and configure which will be executed in the AB test variation.
You cannot upload code via the Optimizely interface or change the code in any way after you submitted the app to Apple. Basically it’s just a glorified boolean(or number) variable to determine which case of an if-else should be executed.</p>
<p><br /></p>
<hr />
<p><br /></p>
<p>You can customize which users should see a test with audience targeting using tags and a Universal User ID:</p>
<h4 id="tags">Tags</h4>
<p>Tags are just key-value pairs which you can set on runtime for a specific user. It’s then possible to show a test only to users with certain tags. The tag matching queries are quite flexible. You can construct “and”, “or” and even partial match queries. For example you can define tags to target only your most active users or users who never bought anything etc..</p>
<p>We are even using tags for inhouse testing and simply defined a tag “BetaTesting” which is only set in our debug and inhouse builds. Targeting our AB test this way we can do both, avoid influencing live running AB tests with data from ourself and testing future AB tests in a more realistic environment than Optimizly’s built in preview mode.</p>
<h4 id="universal-user-id">Universal User ID</h4>
<p>The Universal User ID allows you to deliver a consistent experience across devices for your users. You can hash any user identifying value and pass it to the SDK. Any user with the same Universal User ID will be put into the same bucket.</p>
<p><br /></p>
<hr />
<p><br /></p>
<p>Of course an important part of AB testing is tracking which version performs better. Optimizely offers several tracking mechanisms:</p>
<h4 id="tap-goalsevents">Tap Goals/Events</h4>
<p>You can track the click on certain elements without writing any code and just using the same mechanisms as the UI editor.</p>
<h4 id="view-goalsevents">View Goals/Events</h4>
<p>Optimizley can also fire an event when a view is shown to the user. You also set this up by just using the UI editor.
I think this kind of tracking is a bit fuzzy - what counts as “view was shown”? iOS developers might know that it’s not always trivial to get notified when a certain view appears on screen so that the user can see it.</p>
<h4 id="custom-goalsevents">Custom Goals/Events</h4>
<p>This is my preferred method. You can fire goals/events directly in your iOS code using the Optimizely SDK. Here you as a developer have the full control about when and how often the event will be fired.</p>
<h4 id="revenue-tracking">Revenue Tracking</h4>
<p>With revenue tracking it is possible to track the amount of money a user spent in the app - or any other relevant increasing number. Basically it’s just a counter with a name which you can increase by firing events. This is especially great if your test doesn’t have that one action that you want the user to do, but if you want to optimize retention or overall revenue.</p>
<p>You can use your existing tracking framework to fire events/goals, e.g. Google Analytics, but this requires you to use the native Google Analytics SDK, which might not be the case if you’re using an aggregator framework like Tealium.</p>
<p><br /></p>
<hr />
<p><br /></p>
<p>Optimizely collects all the data for you and presents them in nice interactive graphs. You can see the usual statistics of triggered events for each variation, whether the test reached a statistical significance, conversion rate, difference interval, improvement in percent, …</p>
<p>They even have an option to export the data as csv - which Amazon AB Testing didn’t offer.</p>
<h2 id="evaluation">Evaluation</h2>
<p>To wrap it up here’s a little summary with my personal pros and cons of Optimizely.</p>
<h4 id="pros">Pros:</h4>
<ul>
<li>It works cross platform</li>
<li>It is quite powerful</li>
<li>There’s a good and detailed <a href="http://developers.optimizely.com/ios/reference/index.html">documentation</a></li>
<li>You can edit running tests - this is especially helpful while developing and during the QA phase. Amazon AB testing requires you to create a copy every time you want to change something after starting the test once.</li>
<li>It’s possible to reset the recorded tracking data of the test (e.g. after you finished your local tests)</li>
<li>Direct support for partial rollouts: You can specify that only X % of your users participate in a test.</li>
</ul>
<h4 id="cons">Cons:</h4>
<ul>
<li>You always need to connect a device/simulator with Optimizely (put your app into Edit Mode) to edit the parameters of the variation - even if you don’t use the UI editor and just want to edit the value of a live variable.</li>
<li>The UI editor is sometimes unreliable and even causes bugs in your app (sometimes even in preview mode). E.g. it hides the status bar and I even had a case where suddenly my table view cells had an incorrect size.</li>
<li>You cannot explicitly trigger the tracking event for “experiment started”. It happens implicitly when you first request the value of a live variable or similar.</li>
</ul>
Sun, 18 Oct 2015 21:45:00 +0000http://www.floriangoessler.de/ios/2015/10/18/ABTesting.html
http://www.floriangoessler.de/ios/2015/10/18/ABTesting.htmliosLearning Resources for iOS Devs<p>With this post I want to give prospective iOS Devs some links to really good learning resources. And also more experienced Devs might learn something from some of the Blogs ;-)</p>
<h1 id="tutorials">Tutorials</h1>
<h4 id="standford-ios-course-cs-193p--itunes-u"><a href="https://itunes.apple.com/de/course/developing-ios-8-apps-swift/id961180099">Standford iOS course (CS 193P) @ iTunes U</a></h4>
<p>This course is really good and you can usually follow it including all exercises. It’s maybe a bit more ‘academic’ since it’s a university lecture and you should already be familiar with object oriented programming. Since it’s an iTunes U course it works nicely with all your Apple devices.
I suspect that there’ll be a new Swift 2.0 version of the course this winter.</p>
<h4 id="ray-wenderlich"><a href="http://www.raywenderlich.com">Ray Wenderlich</a></h4>
<p>Probably the biggest source of iOS related tutorials. They cover basically everything in the iOS ecosystem. Most of the tutorials are free. Only some are paid. But even that’s totally okay - we all need to earn money and they provide really good quality. Usually they also update their older tutorials for new Swift Syntax etc.</p>
<h1 id="blogs">Blogs</h1>
<h4 id="nshipster"><a href="http://nshipster.com">NSHipster</a></h4>
<p>Started by the legend <a href="https://twitter.com/mattt">Mattt Thompson</a> (<a href="https://github.com/AFNetworking/AFNetworking">AFNetworking</a> FTW!) this is a really nice blog about the not so often used features of iOS and OS X. Some of the topics are a bit advanced and maybe not that practical but it’s awesome to see what’s possible.</p>
<h4 id="apple-swift-blog"><a href="https://developer.apple.com/swift/blog/">Apple Swift Blog</a></h4>
<p>Apple’s only official Blog. Always worth a look about new Swift stuff or if you want to learn more about it’s internals.</p>
<h4 id="objcio"><a href="https://www.objc.io">objc.io</a></h4>
<p>A nice page with a lot of resources about all sorts of topics. They usually have really great authors and are also writing some books at the moment. And they are from Berlin <em>yeah</em>!</p>
<h4 id="natasha-the-robot"><a href="http://natashatherobot.com">Natasha the Robot</a></h4>
<p>I wish I could keep Natasha’s pace of creating blog posts. She has a lot of small stuff and I always enjoy reading her posts.</p>
<h4 id="mike-ash"><a href="https://www.mikeash.com/pyblog/">Mike Ash</a></h4>
<p>A very interesting blog mostly about the lower level stuff. He usually has a very close and critical look at the APIs.</p>
<h1 id="documentation">Documentation</h1>
<h4 id="apple-docu"><a href="https://developer.apple.com/library/ios/navigation/">Apple Docu</a></h4>
<p>Might seem trivial but read the documentation! And not only those nice class references. There are a lot of guides and demo projects.</p>
<h4 id="ios-human-interface-guidelines"><a href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/">iOS Human Interface Guidelines</a></h4>
<p>You might not be the designer in your team, nevertheless these guidelines are a mandatory read for iOS Devs! It’s just part of knowing how the system works to provide the best possible solution.</p>
<h4 id="wwdc-videos"><a href="https://developer.apple.com/videos/">WWDC Videos</a></h4>
<p>Great videos - I love Apple’s way of presenting stuff ;-). You can also download their slides as PDFs and skim through them if you don’t want to watch a whole 45-50min video.</p>
<h1 id="newsletter--news">Newsletter &amp; News</h1>
<h4 id="dave-werver-ios-newsletter"><a href="https://iosdevweekly.com">Dave Werver iOS Newsletter</a></h4>
<p>This one is mandatory! Get the best news and posts of the week every Friday.</p>
<h4 id="macrumors"><a href="http://www.macrumors.com">MacRumors</a></h4>
<p>Good news site with focus on Apple stuff. Nice to stay up to date on the ‘business’ side of Apple stuff or to read something while you’re compiling your project from scratch because you had to delete your ‘Derived Data’ folder once more ;-).</p>
Tue, 29 Sep 2015 11:15:00 +0000http://www.floriangoessler.de/ios/2015/09/29/Learning-Resources-for-iOS-Devs.html
http://www.floriangoessler.de/ios/2015/09/29/Learning-Resources-for-iOS-Devs.htmliosKeep it Close<p>Structuring the files in a project in a scalable way usually doesn’t have the highest priority when you start your small app project, but with an increasing size of code and number of teammembers working on it, a good project structure can significantly improve the understandability of the project. I want to share my thoughts about what I think is the best approach for it.</p>
<!--more-->
<p>Starting your project it might seem to be a good thing to sort your files based on their role in the MVC pattern. You create a group - or even better a group based on a folder! - for your controllers, one for your models, maybe one for networking stuff, one for custom UIViews and also one for auxiliary stuff.</p>
<p>This might look something like this:</p>
<p><img src="http://www.floriangoessler.de/images/keep-it-close/Step1.png" alt="Step1" class="scale-down-img center-image" /></p>
<p>As the project grows you discover that you need subfolders based on the features (e.g. one for the newsfeed, one for the chat and one for the store), so you add some in each folder:</p>
<p><img src="http://www.floriangoessler.de/images/keep-it-close/Step2.png" alt="Step2" class="scale-down-img center-image" /></p>
<p>Since you are a good programmer and write unit tests, you mirror the structure in your test directory and have an even larger tree!</p>
<h2 id="whats-the-problem-with-such-a-structure">What’s the problem with such a structure?</h2>
<p>As your app grows you add more and more features and more and more subfolders in subfolders and so on. Now you want to make changes to one feature. Since it’s a complex change you need to modify your networking code for it, the model and of course the view controller. Also you need to adjust the unit tests. When you now try to use the project navigator you need to scroll all the time since you have to expand a total of 6 branches!</p>
<h2 id="how-can-we-do-better">How can we do better?</h2>
<p>Group by feature - not by responsibility:</p>
<p><img src="http://www.floriangoessler.de/images/keep-it-close/Step3.png" alt="Step3" class="scale-down-img center-image" /></p>
<p>When we’re editing one feature we now only have to expand 2 branches - one for implementations and one for tests.</p>
<p>But we can do even better! Since we’re not bound to packages and stuff like that, as we are in other languages (e.g. Java), and membership to a target (e.g. app or unit-test target) is configured in the project file itself, we can even move our unit tests close to the implementation!</p>
<p><img src="http://www.floriangoessler.de/images/keep-it-close/UnitTestsClose.png" alt="UnitTestsClose" class="scale-down-img center-image" /></p>
<p>The gist of it: Base your project structure on features and keep stuff that you need to edit at the same time close together. This makes navigation way easier and for new developers joining your team it’s a lot easier to understand the project and it’s features just by looking at the project structure.</p>
<p>It’s also nice to mirror your project structure in the file system. This makes it easier to find files without opening Xcode, to see which group a files belongs to in git logs and diffs and also if you browse the project on GitHub. Unfortunately Xcode doesn’t create folders for new groups automatically but you can easily assign a folder to group in the file inspector after selecting the group in the project navigator:</p>
<p><img src="http://www.floriangoessler.de/images/keep-it-close/FileInspector.png" alt="FileInspector" class="scale-down-img center-image" /></p>
<p>PS: You can also have multiple asset catalogues and storyboards per project - one per feature ;-)</p>
Sun, 06 Sep 2015 11:16:00 +0000http://www.floriangoessler.de/ios/2015/09/06/Keep-it-close.html
http://www.floriangoessler.de/ios/2015/09/06/Keep-it-close.htmliosHTTP/2 on iOS<p><a href="https://en.wikipedia.org/wiki/HTTP/2">HTTP/2</a> was finalized earlier this year, published as <a href="https://tools.ietf.org/html/rfc7540">RFC 7540</a> and is already integrated in iOS 9 and OS X El Capitan. Additionally Apple is pushing HTTP/2 aggressively by providing the new Apple Push Notification Service (APNs) only via HTTP/2 (<a href="https://developer.apple.com/videos/wwdc/2015/?id=720">WWDC Session 720 - What’s New in Notifications - starting ~16:40</a>). HTTP/2 is a great step for the web and especially for mobile devices because it solves some common problems of HTTP 1.1.</p>
<h3 id="http2-vs-http-11">HTTP/2 vs HTTP 1.1</h3>
<p>If you’re already familiar with the advantages of HTTP/2 you might want to skip this section. ;-)</p>
<p>The two most important goals of HTTP/2 for us as app developers are:</p>
<ol>
<li>High level compatibility with HTTP 1.1 - same methods (GET, PUT, POST, …), status codes (200, 404, 500,…), URIs and header fields.</li>
<li>Improved latency</li>
</ol>
<p>The first thing is important for us, because we don’t need to change any application logic to support HTTP/2.
The second thing is important for us, because our mobile devices often operate under high latency conditions.</p>
<p>The main problem of HTTP 1.1 is it’s strict FIFO order of request and the resulting head-of-line blocking problem. Request are always executed in the order in which they are send. This means a large and slow request at the beginning of a connection blocks all other request until it completes. Additionally HTTP 1.1 uses a textual header format which is an overhead when sending a lot of small requests.</p>
<p>Features that make HTTP/2 faster than HTTP 1.1 are:</p>
<ul>
<li>Only one TCP connection (per Host)</li>
<li>Multiplexed connection</li>
<li>Priorities for requests</li>
<li>Binary protocol - not textual</li>
<li>Header compression</li>
<li>Server push technologies</li>
</ul>
<p>To learn more about HTTP/2 I recommend the <a href="https://developer.apple.com/videos/wwdc/2015/?id=711">WWDC 2015 Session 711 - Networking with NSURLSession - starting ~13:10</a>.</p>
<h3 id="how-to-test-whether-we-are-communicating-via-http2">How to test whether we are communicating via HTTP/2?</h3>
<p>Unfortunately <code class="highlighter-rouge">NSURLSession</code> doesn’t give us any information about the used protocol version. There’s an enhancement request and <a href="https://forums.developer.apple.com/thread/12466">little discussion in the Apple Developer Forums</a>, but I don’t think that we’ll see an API for it in the final iOS 9.0 release.</p>
<p>Usually I use <a href="http://www.charlesproxy.com">Charles Proxy</a> to have a look at my outgoing network requests but apparently Charles doesn’t support neither HTTP/2 nor SPDY. Wireshark is another alternative to inspect your network traffic but unfortunately I had some issues running it on OS X 10.11, but in <a href="https://wiki.wireshark.org/HTTP2">theory</a> you should be able to see whether a connection was made via HTTP 1.1 or HTTP/2.</p>
<p>Of course you can have a look at your server logs, but maybe you don’t have access to them or your server isn’t supporting HTTP/2 yet.</p>
<p>What’s left is this nice <a href="https://http2.akamai.com">test page from Akamai</a>. It gives you a little message about whether you successfully connected to it over HTTP/2 or not.</p>
<h3 id="http2-on-ios">HTTP/2 on iOS</h3>
<p>So lets use this Akamai page to test our beloved iOS! Open the page in Safari on iOS 8 and you should see a message <code class="highlighter-rouge">This browser is not HTTP/2 enabled.</code>. If you use your iOS 9 beta device and navigate to the same page you get the more friendly <code class="highlighter-rouge">You are using HTTP/2 right now!</code> message. OK - system apps work.</p>
<p>Now we want to use our own app and send a simple request via good old <code class="highlighter-rouge">NSURLConnection</code>:</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="k">let</span> <span class="nv">request</span> <span class="o">=</span> <span class="kt">NSURLRequest</span><span class="p">(</span><span class="kt">URL</span><span class="p">:</span> <span class="kt">NSURL</span><span class="p">(</span><span class="nv">string</span><span class="p">:</span> <span class="s">"https://http2.akamai.com"</span><span class="p">)</span><span class="o">!</span><span class="p">)</span>
<span class="kt">NSURLConnection</span><span class="o">.</span><span class="nf">sendAsynchronousRequest</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="nv">queue</span><span class="p">:</span> <span class="kt">NSOperationQueue</span><span class="o">.</span><span class="nf">mainQueue</span><span class="p">(),</span> <span class="nv">completionHandler</span><span class="p">:</span> <span class="p">{</span> <span class="p">(</span><span class="n">res</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span> <span class="k">in</span>
<span class="k">if</span> <span class="n">error</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="o">&amp;&amp;</span> <span class="k">let</span> <span class="nv">data</span> <span class="o">=</span> <span class="n">data</span> <span class="o">&amp;&amp;</span> <span class="k">let</span> <span class="nv">str</span> <span class="o">=</span> <span class="kt">NSString</span><span class="p">(</span><span class="nv">data</span><span class="p">:</span> <span class="n">data</span><span class="p">,</span> <span class="nv">encoding</span><span class="p">:</span> <span class="kt">NSUTF8StringEncoding</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">str</span><span class="o">.</span><span class="nf">containsString</span><span class="p">(</span><span class="s">"You are using HTTP/2 right now!"</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">NSLog</span><span class="p">(</span><span class="s">"Used HTTP/2"</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="kt">NSLog</span><span class="p">(</span><span class="s">"Used HTTP 1.1"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// error...</span>
<span class="p">}</span>
<span class="p">})</span></code></pre></figure>
<p>Have a look at the output: <code class="highlighter-rouge">Used HTTP 1.1</code> Wait?! Why isn’t it using HTTP/2?</p>
<p>The reason is simple: <strong><code class="highlighter-rouge">NSURLConnection</code> is deprecated</strong> in iOS 9 and OS X 10.11 and therefore doesn’t support HTTP/2! It’s a pretty old API and the more modern <code class="highlighter-rouge">NSURLSession</code> is around for quite a while now (since iOS 7.0).</p>
<p>Using <code class="highlighter-rouge">NSURLSession</code>…</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="k">let</span> <span class="nv">url</span> <span class="o">=</span> <span class="kt">NSURL</span><span class="p">(</span><span class="nv">string</span><span class="p">:</span> <span class="s">"https://http2.akamai.com"</span><span class="p">)</span><span class="o">!</span>
<span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">NSURLSession</span><span class="o">.</span><span class="nf">sharedSession</span><span class="p">()</span><span class="o">.</span><span class="nf">dataTaskWithURL</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="p">{</span> <span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">res</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span> <span class="k">in</span>
<span class="k">if</span> <span class="n">error</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="o">&amp;&amp;</span> <span class="k">let</span> <span class="nv">data</span> <span class="o">=</span> <span class="n">data</span> <span class="o">&amp;&amp;</span> <span class="k">let</span> <span class="nv">str</span> <span class="o">=</span> <span class="kt">NSString</span><span class="p">(</span><span class="nv">data</span><span class="p">:</span> <span class="n">data</span><span class="p">,</span> <span class="nv">encoding</span><span class="p">:</span> <span class="kt">NSUTF8StringEncoding</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">str</span><span class="o">.</span><span class="nf">containsString</span><span class="p">(</span><span class="s">"You are using HTTP/2 right now!"</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">NSLog</span><span class="p">(</span><span class="s">"Used HTTP/2"</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="kt">NSLog</span><span class="p">(</span><span class="s">"Used HTTP 1.1"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// error...</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">task</span><span class="o">.</span><span class="nf">resume</span><span class="p">()</span></code></pre></figure>
<p>.. iOS now sends a nice HTTP/2 request!</p>
<p>Having those two networking APIs it’s easy to do some benchmarking in a single app. I used the handy Network Link Conditioner of iOS (settings app -&gt; developer menu) to simulate different network conditions. You can find the complete sample app that I used to generate the results <a href="https://github.com/FGoessler/iOS-HTTP2-Test">here</a>.</p>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.1', {packages: ['line']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Try');
data.addColumn('number', '3G HTTP 1.1');
data.addColumn('number', '3G HTTP/2');
data.addColumn('number', 'DSL (2K) HTTP 1.1');
data.addColumn('number', 'DSL (2K) HTTP/2');
data.addRows([
["#1", 1.942, 2.015, 0.944, 0.503 ],
["#2", 1.956, 0.546, 0.368, 0.246 ],
["#3", 0.652, 0.678, 0.349, 0.263 ],
["#4", 0.739, 0.703, 0.337, 0.253 ],
["#5", 0.685, 0.521, 0.335, 0.248 ],
["#6", 1.592, 0.511, 0.491, 0.277 ],
["#7", 0.790, 0.818, 0.332, 0.259 ],
["#8", 0.580, 0.701, 0.339, 0.274 ]
]);
var options = {
chart: {
subtitle: 'Elapsed time in seconds'
},
height: 300
};
var chart = new google.charts.Line(document.getElementById('single-req-times'));
chart.draw(data, options);
}
</script>
<p><strong>Sending a single request</strong></p>
<div id="single-req-times"></div>
<table class="full-width hide-on-mobile">
<thead>
<tr>
<th>Setup</th>
<th style="text-align: right">Try #1</th>
<th style="text-align: right">Try #2</th>
<th style="text-align: right">Try #3</th>
<th style="text-align: right">Try #4</th>
<th style="text-align: right">Try #5</th>
<th style="text-align: right">Try #6</th>
<th style="text-align: right">Try #7</th>
<th style="text-align: right">Try #8</th>
<th style="text-align: right">Average</th>
</tr>
</thead>
<tbody>
<tr>
<td>3G HTTP 1.1</td>
<td style="text-align: right">1.942</td>
<td style="text-align: right">1.956</td>
<td style="text-align: right">0.652</td>
<td style="text-align: right">0.739</td>
<td style="text-align: right">0.685</td>
<td style="text-align: right">1.592</td>
<td style="text-align: right">0.790</td>
<td style="text-align: right">0.580</td>
<td style="text-align: right">1.117</td>
</tr>
<tr>
<td>3G HTTP/2</td>
<td style="text-align: right">2.015</td>
<td style="text-align: right">0.546</td>
<td style="text-align: right">0.678</td>
<td style="text-align: right">0.703</td>
<td style="text-align: right">0.521</td>
<td style="text-align: right">0.511</td>
<td style="text-align: right">0.818</td>
<td style="text-align: right">0.701</td>
<td style="text-align: right">0.812</td>
</tr>
<tr>
<td>DSL (2K) HTTP 1.1</td>
<td style="text-align: right"> 0.944</td>
<td style="text-align: right">0.368</td>
<td style="text-align: right">0.349</td>
<td style="text-align: right">0.337</td>
<td style="text-align: right">0.335</td>
<td style="text-align: right">0.491</td>
<td style="text-align: right">0.332</td>
<td style="text-align: right">0.339</td>
<td style="text-align: right">0.437</td>
</tr>
<tr>
<td>DSL (2K) HTTP/2</td>
<td style="text-align: right">0.503</td>
<td style="text-align: right">0.246</td>
<td style="text-align: right">0.263</td>
<td style="text-align: right">0.253</td>
<td style="text-align: right">0.248</td>
<td style="text-align: right">0.277</td>
<td style="text-align: right">0.259</td>
<td style="text-align: right">0.274</td>
<td style="text-align: right">0.290</td>
</tr>
</tbody>
</table>
<p>For 3G that’s a speedup of ~1.376. For DSL (2K) it’s a speedup of ~1.507.</p>
<script type="text/javascript">
google.load('visualization', '1.1', {packages: ['line']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Try');
data.addColumn('number', '3G HTTP 1.1');
data.addColumn('number', '3G HTTP/2');
data.addColumn('number', 'DSL (2K) HTTP 1.1');
data.addColumn('number', 'DSL (2K) HTTP/2');
data.addRows([
["#1", 30.108, 18.223, 7.299, 3.773],
["#2", 26.406, 22.838, 7.562, 3.676],
["#3", 30.970, 15.896, 6.801, 3.662],
["#4", 27.686, 17.721, 6.442, 3.720],
["#5", 28.045, 23.195, 6.706, 3.753],
["#6", 27.064, 16.518, 6.597, 3.678],
["#7", 26.116, 22.089, 7.007, 3.668],
["#8", 26.593, 14.888, 6.842, 3.702]
]);
var options = {
chart: {
subtitle: 'Elapsed time in seconds'
},
height: 300
};
var chart = new google.charts.Line(document.getElementById('multi-req-times'));
chart.draw(data, options);
}
</script>
<p><strong>Sending 361 requests (32x32 pixel PNG images)</strong></p>
<div id="multi-req-times"></div>
<table class="full-width hide-on-mobile">
<thead>
<tr>
<th>Setup</th>
<th style="text-align: right">Try #1</th>
<th style="text-align: right">Try #2</th>
<th style="text-align: right">Try #3</th>
<th style="text-align: right">Try #4</th>
<th style="text-align: right">Try #5</th>
<th style="text-align: right">Try #6</th>
<th style="text-align: right">Try #7</th>
<th style="text-align: right">Try #8</th>
<th style="text-align: right">Average</th>
</tr>
</thead>
<tbody>
<tr>
<td>3G HTTP 1.1</td>
<td style="text-align: right">30.108</td>
<td style="text-align: right">26.406</td>
<td style="text-align: right">30.970</td>
<td style="text-align: right">27.686</td>
<td style="text-align: right">28.045</td>
<td style="text-align: right">27.064</td>
<td style="text-align: right">26.116</td>
<td style="text-align: right">26.593</td>
<td style="text-align: right">27.874</td>
</tr>
<tr>
<td>3G HTTP/2</td>
<td style="text-align: right">18.223</td>
<td style="text-align: right">22.838</td>
<td style="text-align: right">15.896</td>
<td style="text-align: right">17.721</td>
<td style="text-align: right">23.195</td>
<td style="text-align: right">16.518</td>
<td style="text-align: right">22.089</td>
<td style="text-align: right">14.888</td>
<td style="text-align: right">18.921</td>
</tr>
<tr>
<td>DSL (2K) HTTP 1.1</td>
<td style="text-align: right">7.299</td>
<td style="text-align: right">7.562</td>
<td style="text-align: right">6.801</td>
<td style="text-align: right">6.442</td>
<td style="text-align: right">6.706</td>
<td style="text-align: right">6.597</td>
<td style="text-align: right">7.007</td>
<td style="text-align: right">6.842</td>
<td style="text-align: right">6.907</td>
</tr>
<tr>
<td>DSL (2K) HTTP/2</td>
<td style="text-align: right">3.773</td>
<td style="text-align: right">3.676</td>
<td style="text-align: right">3.662</td>
<td style="text-align: right">3.720</td>
<td style="text-align: right">3.753</td>
<td style="text-align: right">3.678</td>
<td style="text-align: right">3.668</td>
<td style="text-align: right">3.702</td>
<td style="text-align: right">3.704</td>
</tr>
</tbody>
</table>
<p>For 3G that’s a speedup of ~1.473. For DSL (2K) it’s a speedup of ~1.865.</p>
<p>As we can see requests over a high latency network connection with several requests benefit the most from HTTP/2. If you’re loading a collection of images from your servers or sending multiple requests for other reasons at once, your app might benefit a lot from HTTP/2. If you’re only sending one request per view controller you probably won’t notice a large difference on the user level.</p>
<h3 id="additional-notes">Additional Notes</h3>
<p>It’s not enough that the app is running on an iOS 9 device to use HTTP/2 - it must be <strong>build</strong> against iOS 9 <strong>and run</strong> on an iOS 9 device!</p>
<p>A list of servers already supporting HTTP/2 can be found on <a href="https://github.com/http2/http2-spec/wiki/Implementations">GitHub</a>.</p>
<p>Another nice library/tool for HTTP/2 connections is <a href="https://nghttp2.org">nghttp2</a>. You can send HTTP/2 request via <a href="https://nghttp2.org/documentation/nghttp.1.html">nghttp(1)</a> or even setup your own small test server with <a href="https://nghttp2.org/documentation/nghttpd.1.html">nghttpd(1)</a>.</p>
<p>It’s worth noting that HTTP/2 supports encrypted connections (HTTPS/TLS) as well as unencrypted ones, but most clients (e.g. Firefox &amp; Chrome) do not support unencrypted connections and also Apple’s new <a href="https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/">ATS</a> mechanism pushes us to use only encrypted connections!</p>
<p>To sum it up here is a checklist to support HTTP/2 in your app:</p>
<ul>
<li>Update your servers to support HTTP/2</li>
<li>Update your servers to support up-to-date encryption (aka HTTPS/TLS)</li>
<li>Build against the iOS 9 SDK</li>
<li>Replace all <code class="highlighter-rouge">NSURLConnection</code> API calls with <code class="highlighter-rouge">NSURLSession</code></li>
</ul>
Sun, 30 Aug 2015 18:38:00 +0000http://www.floriangoessler.de/ios/2015/08/30/HTTP2-on-iOS.html
http://www.floriangoessler.de/ios/2015/08/30/HTTP2-on-iOS.htmlios