Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You can totally do pure UIViewControllers with Swift. Just initialize them with all the data they need and give them callbacks (or "handlers" if you want to call them that) for every UI control. Keep a reference to your UINavigationController somewhere outside (in AppDelegate? Hopefully not, but you could :p) any of the UIViewControllers, and use pushViewController(screenYouWantToShow(dataToPassToScreen, callback1, callback2)) to move between views.

If you want to "edit" the previous screen in the stack you just build a new version of the screen you want to "edit" then remove old one from the UINavigationView.viewControllers array and insert the new one. Then popViewControllerAnimated() back to it. It works very well.

Making iOS apps this way has been a dream come true for me.



having worked on a number of iOS apps (everywhere from 5k loc to 80k loc), i have literally never seen anyone work any other way -- you just put `[self renderView:model]` on your controllers and it's a pure function which sets up the state such that the system `layoutSubviews` call is also pure function.

i havent seen that "build a new version of the previous screen" tho, at least not the way you describe -- most of the time you just rely on `viewWillAppear` calling `renderView:model`, and `viewWillAppear` gets called on `popViewController` by default.


Handlers for every UI control ? Could you elaborate on that part ?

Does this approach scale well ? Have you done large apps ?

FB has an open source ComponentKit Framework.


"Handlers for every UI control?"

Sure, for every piece of the UI that commits a change to the model, such as a save button, you need a callback to pass the updated model to.

You pass a "movie" object and a "saveMovie()" callback into a screen that allows you to edit the details of a movie. You edit the fields then click "save". The code that runs when the "save" button is clicked builds a new movie object then masses the new movie object to the the callback, like this "saveMovie(editedMovie)". The "saveMovie()" callback makes the API calls, database calls, etc, and the movie editing screen doesn't need to to anything else after that, and inside "saveMovie()" you can push a new screen, pop back to the previous one, or whatever. Does that make sense?

"Does this approach scale well?"

I don't see how it could be much worse than making API calls from UIViewControllers. If you do this, you're instantiating new UIViewControllers more often, so if you're loading a bunch of images on a certain view you may want to hang on to a reference to that particular view instead of building a new one each time. But, in my experience, the code ends up being a LOT cleaner than if you treat your UIViewControllers as mutable objects. So from an architecture and maintainability standpoint, it scales really well.


I tried this approach with my current Swift project, but I found that it doesn't scale to a certain level of complexity. A ton of the UIKit APIs are naturally stateful, so you end up having to work around them in weird ways. Animation is particularly hard when your view controllers are pure. The solution I opted for was to instead create a unidirectional data flow and just "refresh" the state of the VC every time it gets passed different data. This way, you get most of the benefits of one-way data flow and the state of your VCs is (somewhat) pure, but you can easily drop down and use the UIKit APIs as needed.


I agree. UIKit is very OO. The style of UI development exemplified by React/Om/Reagent/Clojurescript, etc, is totally different.


I see what you mean. I'd probably run into issues if I was doing a lot of transitions animated transitions and interactions. With my method nothing is really stopping you from creating a VC that has a public refresh function though. It would just have to break the pattern of ask the others a little bit.


> Have you done large apps ?

At work we're at 10k loc which isn't huge but it's fairly large for a clojurescript app. Middleware on event handlers is a great abstraction. It's only been a few weeks since the refactor and there are only three of us on the team but I'm not foreseeing any scaling problems. The only changes we made are about 20 middlewares and namespacing our event keywords. We experimented with a forked version of the framework and running multiple re-frame apps nested inside each other but it wound up not being worth the effort.

The only scaling hazard I know of is that re-frame has an internal global atom so that might cause a problem if you're mixing multiple re-frame apps on a single page but it doesn't affect us and reworking the framework to not use a global isn't too difficult.


The idea is to get away from callbacks altogether. That is the idea of FB React and Om/Reagent. What you describe is not at all the paradigm for UI development I'm talking about.


I understand that, I wasn't saying it was exactly the same. I do think that what I'm doing is better than what iOS tutorials usually teach you to do though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: