Brent Simmons, developer of NetNewsWire, writes about Mac and iOS development, indie apps, and Swift.
HN commenters cite his post on why NetNewsWire is not a web app, and his notes on feed handling and FMDB.
> I'm aware of that–that's why I said it is possible that you can do it from JavaScript. What I'm saying is that the JavaScript layer generally causes issues like this, because UINavigationController only works in specific cases. For example, scrolling only works if you're a singular top-level scroll view. Getting the titles to animate only works if you don't try to modify it after the fact. Putting a button in the navigation bar's title view just makes it mess up when it runs its first layout pass. A lot of frameworks end up doing this, or making it very easy for this to occur, so you end up with "broken" navigation of the likes seen in that GIF. Of course, it's not unusable, so those who aren't as familiar with how it should work don't notice the difference.
Most of those issues that you bring up with UINavigationController are, while annoying, not actually _that_ common in apps, and people run into them at the native level too - it's not entirely a JS issue. Provided you're not doing anything too against the grain (which the Wix API more or less protects novice users from doing), you're unlikely to experience too many issues and it functions as an almost completely indistinguishable UINavigationController experience for pretty much everyone.
As an aside, if React Native would fix TouchableOpacity to follow platform convention, most people would have difficulty detecting RN apps.
> I'm surprised you haven't drawn the cynical conclusion from this: that I'm desperately…
The posts in the first linked series (http://inessential.com/2016/05/) seem to mostly focus on how dynamism can avoid the need for boilerplate. For example, he states that the following code is tedious to write and error-prone:
if localObject.foo != serverObject.foo {
localObject.foo = serverObject.foo
changeDictionary[fooKey] = serverObject.foo
}
if localObject.bar != serverObject.bar {
localObject.foo = serverObject.bar
changeDictionary[barKey] = serverObject.bar
}
But there's another language feature that can replace boilerplate, without dynamism and its associated performance and type safety penalties. A feature that's reviled by many, and was omitted from Swift, but serves this purpose perfectly: macros. What if you could write this?
macro_rules! merge {
($localObject:expr, $serverObject:expr, ($($prop:ident),+)) => {
$(
if $localObject.$prop != $serverObject.$prop {
$localObject.$prop = $serverObject.$prop;
changeDictionary[stringify!($prop)] = $serverObject.$prop;
}
)+
}
}
merge!(localObject, serverObject, (foo, bar, baz));
Actually, this is valid Rust code, as you might have guessed if you know that language. I picked it because it has similar syntax to Swift and a powerful, hygienic macro system. (This case is simple enough that a C macro would also work fine without any ugly arcane stuff -…
I use Forklift. Version 4 just came out this week, with a new quasi-subscription model. Now it's $20/yr, or $35 for 2, but you can keep using the final version that comes out during your subscription period. That's not awful but I'm still disappointed.
My first impression: this is clearly not a "Mac-assed Mac app"[0]. The fonts are weird (but configurable). The keyboard shortcuts are weird (but configurable). The preference pane isn't under the "Double Commander > Settings" menu, but "Configuration > Options", and it doesn't open with "cmd-,", and that doesn't seem to be configurable.
These are not deal breakers. Different doesn't automatically mean bad. In this case, it does mean that you have to learn how to use it from scratch, compared to something like Forklift or Commander One that someone used to Finder can pick up and start using. It also doesn't seem to come with a zillion integrations with cloud services like S3, Box, etc. like the Mac-native options.
These are my first impressions. I've used it for maybe 20 minutes now. That's not a fair shake, and it could be that I'd absolutely love it if I kept at it. Still, it doesn't make me want to keep at it. I could see Double Commander being brilliant if I already used it on Linux and wanted to bring my workflow, settings, plugins, and all that to Mac. I don't think I'd want to start using it here.
[0] https://inessential.com/2020/03/19/proxyman
You're right — users shouldn't expect their apps to get major updates for free. But this is a PR problem, solvable by other means. As a user, I'm OK with it. I've been using Adobe CS 5 for the past 3 years and it's still working great. Were there an upgrade path where I could pay some cash and get the latest version, I would probably do so. Unfortunately, Adobe has decided that they're not the company for me, and so I've been happily moving on to alternatives like Pixelmator and Affinity Designer. From what I've seen in the response to Text Expander's subscription pricing and other similar business model changes, I think many others feel the same as I do: that above all else, the software running on their local machine must continue to work without having to pay a bloody tax.
A text expander is not a "service", nor is a password manager, nor is an audio looper or a to-do lister. To suggest otherwise would be disingenuous. Of course, we don't know what's going to happen in response to this change yet, but statements like Gruber's "win-win-win"[1] and Brent Simmons' request for clarification[2] indicate to me that indie developers will be more than happy to adopt this model with their decidedly non-service software.
[1]: http://daringfireball.net/2016/06/the_new_app_store
[2]: http://inessential.com/2016/06/08/seeking_clarification
It doesn't sound like you've read any of the articles. There are details and tradeoffs and limitations found by the people talking about them. And there is a massive knowledge vacuum because if there is a good solution, it's not something that is obvious and well discussed by Apple. Ignoring and dismissing them doesn't make them actually go away.
Here's two on just the Responder chain:
http://inessential.com/2016/05/17/responder_chain_followup
http://shapeof.com/archives/2016/5/dynamic_swift.html
The bigger point (which is in that first Brent Simmons link) is that people have built all sorts of frameworks and tools over the past 20 years depending using of the dynamic features of Obj-C. Some are Apple's like all the above plus others like Interface Builder and XCTest, but other people have built their own things too that rely on the same concepts. How do these people move forward in a Swift world?
None of these people are arguing that Swift is terrible and going back to Obj-C. They are trying to use Swift. They are only interested in solving the problems they have (and well). When Swift fails to solve a problem or is far worse than its predecessor, there is a problem.
Not everybody can nonchalantly throw their stuff overboard like you are willing to do with Core Data.
I think a big part of what people perceive as being Electron’s fault actually comes down to how the app code is written.
Beyond the regrettable (but hard to avoid) baseline memory usage, startup time, and bundle size, at the end of the day it’s just a browser. Native code might be faster than JS on benchmarks but at the level of clicking a button to perform an action, there’s no technical reason that the latency should be any different, certainly not at the level of 100s of milliseconds. It’s just slow UI code at that point. I daresay the bigger problem is the huge prevalence of slow UI code.
It reminds me of this article on why NetNewsWire (a native Mac RSS reader) is fast - turns out it takes a lot of work beyond just being native! (and a bunch of these strategies have analogs in the JS world too)
https://inessential.com/2020/05/18/why_netnewswire_is_fast