
Katana – Modern Swift framework for creating iOS apps, inspired by React/Redux - Feanim
https://github.com/BendingSpoons/katana-swift
======
king_magic
This feels a bit like a solution without a problem, or maybe more like a giant
sledgehammer-sized solution to 10 or 15 smaller ant-size problems.

I guess I'm just not sure what advantage I'd get by taking a (frankly) mind-
bending approach to building an iOS app instead of following normal iOS
conventions. And just to be clear I've done React development on the web, and
I've thoroughly enjoyed it. Modern web development is mind-bending enough that
React (and other approaches) felt like they brought some sanity to the table,
but this doesn't feel like that. It feels overly complicated for iOS
development, which feels like a largely solve problem.

What am I missing? I'm really not trying to be critical, I'm really trying to
understand why you'd recommend I use this approach over standard iOS patterns.
In the 8 years I've been developing for iOS I've never felt like I needed
anything I've seen in here (or in any of the getting started tutorials I read
through), but I'd like to try to see what I'm missing here.

~~~
danielhooper
I recently worked on an app that adopted a similar framework (ReSwift) and I
hated it for the same reasons you are skeptical. It was needlessly complex,
horrible to try and debug, and was incompatible with the "status-quo" of
standard app development practices.

At the end of the day it was just a bad replacement for Core Data / Realm /
whatever.

I wish I could tell you more but like yourself I really had absolutely no idea
what the point was or what it was supposed to make easier.

~~~
ianterrellwt
I've been working on an app that's more or less using ReSwift (I've hacked on
it a bit). Can you elaborate on what you ran into that was complex/horrible?

~~~
danielhooper
I couldn't fix a lot of UI problems because when trying to trace what was
happening through this system of actions and states I could only find when
these bugs occurred when stepping between lines of machine code.

I can't offer a fair point of view because I don't think the project I was
working on made proper use of ReSwift. It was very difficult to follow the
flow of data and understand why certain things wouldn't work.

~~~
danappelxx
What you're describing doesn't really make any sense... the whole point of
these frameworks is to make your application more predictable. If your layout
isn't right for a particular state, you can rewind back to that exact state
again and again. It sounds like you were using ReSwift wrong, to be honest.
There's not a lot of magic going on in it that would make it hard to debug.

------
21echoes
The one issue I see with bringing Flux/Redux to iOS is that iOS shipped with
unidirectional data flow from day 1 with KVO: view => IBAction on controller
=> model method (incl. any API or CoreData work) => controller is notified of
changes via KVO => rerenders view via a pure function. I don't think it was
struggling for a new, clean solution here in the same way the web was.

That said, for people used to the React patterns, this could be a somewhat
easy way to make the transition over to iOS programming! So that's cool :D

~~~
bsaul
Except kvo doesn't have a sane threading model, nor is it typed, and can crash
your program if you fail to unregister properly. It makes the programs a lot
harder to debug,not simpler.

------
lucaquerella
I'm one of the author of the framework :) please let me know if you like our
approach to apps development we internally use it for creating our own apps at
Bending Spoons ([http://bendingspoons.com](http://bendingspoons.com))

~~~
lisardo
This is great! Is there a way to use with an existing project?

~~~
bolismauro
[https://github.com/BendingSpoons/katana-
swift/issues/79](https://github.com/BendingSpoons/katana-swift/issues/79) ;)

------
nodamage
> logic: the app state is entirely described by a single serializable data
> structure

I'm curious how frameworks like this handle dealing with large amounts of
data? Let's say my data source has 25,000 rows that I need to search and
filter through at any given time.

Using standard iOS paradigms I might store the data in a SQLite database using
Core Data, use an NSFetchedResultsController to search the data, and display
it using a UITableView. Any changes to the underlying data
(insertions/deletions/updates) are automatically tracked and dealt with so the
UITableView is kept up to date as the data changes. Behind the scenes there
are lots of optimizations occurring in Core Data and the
NSFetchedResultsController so only the data for visible rows are loaded into
memory at any given time.

How would I achieve this behavior using a framework like this? How big/complex
can this "single serializable data structure" get?

------
bdrool
Can people please be honest and say "trendy" instead of "modern" if that's
what they actually mean?

------
namuol
If you're willing to take a leap like this for an iOS project, why not just
use React Native? At least with that you get a much more portable codebase,
not to mention the benefits that come with its growing ecosystem.

~~~
scosman
ReactNative wraps up the native controls, often with lowest common denominator
APIs that work across iOS + Android. You can get a basic app up and running
quickly, but when you want to do something more advanced it really slows you
down.

~~~
htormey
Any examples? I've been working with RN for the past few months and it's been
pretty good. Only issues where I had to do some native wrapping were around
background location polling and a client using a Microsoft websocket clone
called signalr. Those things slowed me down.

------
orta
Looking cool, I think iOS development in general could learn a lot from React
+ JS ecosystem. :+1:

~~~
king_magic
What problems do you think the React + JS ecosystem could solve in the iOS
world that haven't already largely been solved by standard iOS development
approaches? I'm legitimately asking here - I been developing for iOS for years
(and more recently with React from time to time for the web), and I've never
once felt that standard iOS conventions/patterns were lacking compared to the
React/JS ecosystem, but I would like to understand your point of view.

~~~
Arcanum-XIII
Biggest problem is the lack of a proper way to update data thru the app. More
often than not, we end with a big mess of singleton, notification, badly
implemented kvo... and if you're not lucky, you'll have to fight to get an
authoritative source for the data, or the latest one. When I see what's
possible with solution like Om, I'm very envious (not that it's a silver
bullet, but it's a major step forward in my point of view)

~~~
jinjin2
You should try Realm. We radically simplified the architecture of our app by
using Realm as the authoritative source of data (equivalent to a redux store)
and then having all the views reacting to changes in the model. This also
allowed us to have all writes happening background threads.

~~~
king_magic
I am a huge fan of Realm; I have personally moved to a model where I use Realm
as the authoritative source of data. It works very well.

------
mtzaldo
I found the following repo example of something React inspired too, but using
f#. There's also a youtube video with a great explanation of the concepts on
the repo. This guy also created an IDE for F# for the iOS. It is a great
resource too... github:
[https://github.com/praeclarum/FunctionalMeetup](https://github.com/praeclarum/FunctionalMeetup)
youtube video:
[https://www.youtube.com/watch?v=_Qk7ZcyYZwA](https://www.youtube.com/watch?v=_Qk7ZcyYZwA)
ios app: [https://itunes.apple.com/us/app/continuous-.net-c-and-f-
ide/...](https://itunes.apple.com/us/app/continuous-.net-c-and-f-
ide/id1095213378?mt=8)

------
interpol_p
I have kind of gone half-way between a full-blown React model and MVC for iOS
development.

The last big project I worked on in Swift used an MVVM-style design. But I
encapsulated the application state in a Swift enum.

The enum adhered to a protocol `AppState` which defined a method to turn an
`AppState` into a view controller, as well as a static function to transition
a view controller to a new `AppState`. Swift's strong type system ensured that
it was very easy to guarantee that every view controller / view model had
access to well-defined data types and that the flow of information only
happened in one direction.

This meant that the entire transition logic for the application sat in one
relatively small file that handled how each state could be displayed (and
whether special cases were needed if coming from a particular state).

So for example, to present an alert in the application a view controller would
ask its view model for the next AppState, and then ask to transition to that
state.

E.g., in the view controller:

    
    
        let nextState = viewModel.nextStateForSomeButtonPressed()
    
        AppState.transitionViewToState(self, nextState)
    

And the view model's next state logic might be:

    
    
        return MyAppState.BasicAlert("Title", "Message")
    

The enum .BasicAlert has all the logic needed to transform into a view
controller (in this case a `UIAlertController`), and the transitionViewToState
has all the logic needed to present that controller.

I have since found that this is one of the most pleasurable projects to
maintain and update.

Edit:

This also allowed some nice functions to be written, like:

    
    
        func initialApplicationState() -> [AppState]
    

Which the AppDelegate uses on startup to display the correct array of view
controllers (in this case, the app displays a tutorial sequence on first-run,
but that logic is completely decoupled from the AppDelegate).

------
mahyarm
How do you deal with the main thread and thread safety? Being able to 'modify'
views off the main thread would be the largest advantage of something like
this, kind of like async display kit

~~~
bolismauro
hey mahyarm, thanks for the feedback

this is definitely something interesting. We started looking into that at the
beginning of the project but later we dropped it since we haven't found a use
case when that was really needed, the performance are quite satisfying at the
moment! Katana already has a diffing algorithm in place and some other
optimizations.

If you have a project that could benefit from it, please open an issue so we
can take a look at it!

------
stiGGG
From the code samples in README:

var payload: ()

What does that mean? What type has payload? I throwed it inside Xcode, it does
compile but i still don't understand it.

~~~
lucaquerella
It's Void. In that example there is no need for the action to have a payload.

~~~
stiGGG
Ah, thanks, didn't know you could declare a Void variable. And Payload is an
associated type of the Protocol, now i got it ;)

------
duaneb
How does diffing work?

~~~
lucaquerella
It's quite long to explain it here, why don't you take a look at the
Node.swift source code, if you have trouble understanding a specific part I'll
be happy to help you.

