Though you explain the alternatives well, I think you missed out on ways to effectively use storyboards.
- If your storyboards are getting huge, you are doing it wrong. Create separate storyboards for each feature, keeping them small and focused, and load them with programatically when needed, or create segues between storyboards. Both methods are straightforward
- You can still use custom, reusable views in story boards by setting the view class in the storyboard to your custom view.
- I don’t see the problem with force unwrapped outlets. They are created this way because they are guaranteed by the system to be present when the view is loaded.
- An alternative to setting the view class (or button class or what have your) in the storyboard is to use protocol extensions to add customizations, and use those in view did load. I find extensions to be even more portable than custom views between projects.
- Storyboard merges can be a pain, I agree, but if you keep the storyboards small, you are less likely to get them. And if you have only one developer responsible for each feature, you should be able to avoid them altogether. If two developers do need to work on one storyboard, adding a view typically is not a problem because it is encapsulated in its own XML block, and should merge without conflict.
I definitely agree the lack of custom inits is annoying, especially if you want to use dependency injection on your view controllers.
Don’t get me wrong, there is definitely a place for creating and adding views programatically, but I think storyboards can save a lot of time and the ability to have visualizations and to use @IBDesignable is really nice.