I look at a 200 lines ViewController class and sigh… Why.. oh… why it looks so ugly? ( I compare it with nice and simple controller’s code in RoR.)
Just to be fair: There are a lot of badly written Rails apps too. However, I am not talking about a difference between good and bad apps.
You can write a solid code for iOS. However, at the end of the day it will be lightyears away in cleanness from RoR code (BTW. I compare it with RoR just because I am familiar with it. I am pretty sure that same comparison will stand for other well established web framework)
This pissed me off and I started to think. Why it’s like that?
Let me start from big rocks
Language
Swift is nice and clean (comparatively to ObjectiveC). However, it’s way less flexible that Ruby. Swift doesn’t have anything close to metaprogramming, it doesn’t have mixins. Hell… even reflection (which I got used in Java) is very weak in Swift. As result, there are bunch of solutions which end up having way more hair in Swift vs Ruby.
JSON deserialization is a perfect example.Ruby has transparent libraries. The best library I found in Swift is EVReflection. Edwin Vermeer found a lot of interesting workaround to create a solution ( he had to use both Swift and ObjectiveC to achieve it). However, taking into account language limitation the solution is still not that transparent (you need to inherit from a specific class, you need workaround for generics, enums, inheritance and so on)
iOS API’s are Objective C and applications are in Swift
Apple did a good job bridging between Swift apps and ObjectiveC core. However, there are seams anyway. As example, some language features as optional protocols available only in ObjectiveC and not available in Swift. On other hand some features are available only in Swift (as example more advanced generics usage). As result some things are hard/impossible to implement.
As example, I was trying to implement generic class to implement UITableViewDataSource protocol to provide data for tables. It moved forward briskly until I stuck with a problem that I can’t pass such (generic) class back to UIKit, because it doesn’t like generics.
Interface builder
I can write whole essay by now why IB is a problem.
The very short summary. IB is a tool for designer (not engineers). It’s hard to diff change. It’s impossible to remove code duplication.
The layout and style are mixed (compare it with how HTML + CSS which keep it separate). It’s not self contained (there is still a lot of spill over in the code to define more complex UI and more complex interaction).
I am strongly appose to WYSIWYG for UI development. It’s nice and fast when you need to put something fast. However, the supportability of WYSIWYG solutions are problematic. (BTW. Android as example provides a good option to look under the hood and directly edit UI definition).
No MVC/No good patterns
Template iOS application doesn’t have a notion of Model (meaning: no directory for model files and no example of a model file). So, each developer implements in it’s own way.
Another problems is that IB contains only part of View. The rest of View spills over to Controller.
On top of that interaction between View and Controller are very rich. As result controller has to implement gazillion interfaces and become unbelievably fat (mixing huge amount of logic which should have been spread across View and Model).
I would probably even generalize it. There is a lack of well defined good patterns. You download a sample app from Apple. You see in it 300 lines controllers, which does gazillions things with methods with dozen levels of depth.
Now let me mention couple of smaller rocks.
There will be dragons as soon as you will try to do something just a little bit more complex,
As example, there is a bug with customer header handling. The whole table will be sliced when you try to delete a row (if you have custom headers). As result you have to apply strange workarounds. The bug was around at least 1.5 year already. Yeah, it’s not the most common case, but it’s not the most rare case.
Another issue. Following segue order will bring your application to it’s knees. (View A -> View B -> View C -> View B). IB doesn’t like circular segues apparently.
The simple stuff works well. Anything more complex require workarounds.
Very rich, but not DRY and sometimes inconsistent API
Apple is gradually making API’s better. However, it takes quite a lot of time.
As example, permission granting was cleaned up a lot in the latest version. However, it still doesn’t feel completely clean. As example, each framework has it’s own API for prompting a user to grant permissions to access some feature (camera, contacts). As result, an application which need to get multiple permission will have to implement almost exact copy of the same code for each framework.
Back to 30k feet view
It’s interesting that web frameworks are much more polished comparatively to iOS (BTW. they are better than Android too).
I believe the underlying reason is web development frameworks having more time to evolve. I would say web had additional decade to figure out the patterns. As result, you have well defined interfaces/patterns on multiple levels.
Secondly, Web development frameworks has less problems with backward compatibility. As example, RoR didn’t have to support old ColdFusion application. Each new framework could have thrown away everything It was easier to come up with new better framework. It’s more complicated for mobile API which is part of OS (a company won’t be willing to throw away whole OS ecosystem to improve API’s).
Thirdly, there is a huge community working on web development frameworks. The community which works on native mobile app development is much smaller (employed by Apple or Google) .
As result, something like RoR solves common problems really-really well, while iOS development is kind of ok, but lacks crispness of web frameworks.