Remix.run Logo
LoganDark 6 hours ago

I recently started writing for macOS in Swift and, holy hell, the debuggability of the windowing toolkits is actually unparalleled. I've never seen something that is this introspectable at runtime, easy to decompile and analyze, intercept and modify, etc. Everything is so modular, with subclassing and delegation patterns everywhere. It seems all because of the Objective-C runtime, as without it you'd end up needing something similar anyway.

You can reach into built-in components and precisely modify just what you want while keeping everything else platform-native and without having to reimplement everything. I've never seen anything like this before, anywhere. Maybe OLE on Windows wanted to be this (I've seen similar capabilities in REALLY OLD software written around OLE!) but the entirety of Windows' interface and shell and user experience was never unified on OLE so its use was always limited to something akin to a plugin layer. (In WordPad, for example)

The only thing that even seems reminiscent is maybe Android Studio, and maybe some "cross-platform" toolkits that are comparatively incredibly immature in other areas. But Android Studio is so largely intolerable that I was never able to dig very far into its debugging capabilities.

I feel like I must be in some sort of honeymoon phase but I 100% completely understand now why many Mac-native apps are Mac-native. I tried to write a WinUI3 app a year or two ago and it was a terrible experience. I tried to get into Android app development some years ago and it was a terrible experience. Writing GUIs for the Linux desktop is also a terrible experience. But macOS? I feel like I want to sleep with it, and I weep for what they've done with liquid glass. I want the perfection that led to Cocoa and all its abstractions. Reading all the really, super old documentation that explains entire subsystems in amazingly technical depth makes me want to SCREAM at how undocumented, unpolished and buggy some of the newer features have gotten.

I've never seen documentation anything like that before, except for Linux, on Raymond Chen's blog, and some reverse-engineering writeups. I do love Linux but its userspace ecosystem just is not for me.

Maybe this is also why Smalltalk fiends are such fans. I should really get into that sometime. Maybe Lisp too.

tpmoney 15 minutes ago | parent | next [-]

Writing objective-c code for mac os GUI apps was one of those things that finally made "interfaces"/"protocols" really click for me as a young developer. Just implement (some, not even all) method in "FooWidgetDelegate", and wire your delegate implementation into the existing widget. `willFrobulateTheBar` in your delegate is called just before a thing happens in the UI and you can usually interfere or modify with the behavior before the UI does it. Then `didFrobulateTheBar` is called after with the old and new values or whatever other context makes sense and you can hook in here for doing other updates in response to the UI getting an update. If you don't implement a protocol method, the default behavior happens, and preserving the default behavior is baked into the process, so you don't have to re-implement the whole widget's behavior just to modify part of it.

It's probably one of the better UI frameworks I think I've used (though admittedly a lot of that also is in part due to "InterfaceBuilder" magic and auto-wiring. Still I often wish for that sort of elegant "billions of hooks, but you only have to care about the ones you want to touch" experience when I've had to use other UI libraries.

kmeisthax 4 hours ago | parent | prev [-]

> Writing GUIs for the Linux desktop is also a terrible experience.

I've found the DX for GTK to be at least tolerable. Not fantastic, but I can at least look at a particular API, guess how the C-based GObject code gets translated by my language bindings of choice, and be correct more often than not. The documentation ranges from serviceable to incomplete, but I can at least find enough discussion online about it to get it to do what I want.

Also, GTK apparently ships with a built-in inspector tool now. Ctrl-Shift-I in basically any GTK app opens it. That alone is extremely useful, and you basically have to do nothing to get it. It's free.

I've never tried Qt. The applications that use it always seem off to me.

As for OLE, you're actually thinking of COM, not OLE. They were co-developed together: COM is a cross-language object system (like GObject), while OLE is a set of COM interfaces for embedding documents in other arbitrary documents. Like, if you want to put a spreadsheet into a Word document, OLE is the way you have to do that. Microsoft even built much of IE[0] on top of OLE to serve as its extension mechanism.

OLE is dead because its use case died. Compound documents as a concept don't really work in the modern era where everything is same-origin or container sandboxed. But COM is still alive and well. It's the glue that holds Windows together - even the Windows desktop shell. All the extension interfaces are just COM. The only difference is that now they started packaging COM objects and interfaces inside of .NET assemblies and calling it "WinRT". But it's the same underlying classes. If you use, say, the Rust windows crate, you're installing a bunch of language bindings built from WinRT metadata that, among other things, call into COM classes that have been there for decades.

Mac apps are Mac native because Apple gives enough of a shit about being visually consistent that anyone using a cross-platform widget toolkit is going to look out of place. Windows abandoned the concept of a unified visual identity when Windows 8 decided to introduce an entirely new visual design built around an entirely new[1] widget toolkit, with no consideration of how you'd apply any of that to apps using USER.dll/Common Controls. As it stands today, Windows does not have a good answer to "what widget toolkit do I use to write my app", and even Microsoft's own software teams either write their own toolkits or just use Electron.

[0] Petition to rename ActiveX to WebOLE

[1] OK, yes, XAML existed in the Vista era, but that was .NET only, and XAML apps didn't look meaningfully different from ones building their own USER.dll window classes like it's 1993.

anthk 41 minutes ago | parent | next [-]

9front can mount old DOC/XLS documents as OLE 'filesystems' first and then extract the tables/text from them.

As for sandboxing, 9front/plan9 uses namespaces, but shared directories exist, of course. That's the point on computing, the user will want to bridge data in one way or another. Be with pipes, with filesystems/clipboard (or a directory acting as a clipboard with objects, which would be the same in the end).

LoganDark 4 hours ago | parent | prev [-]

> As for OLE, you're actually thinking of COM, not OLE. They were co-developed together: COM is a cross-language object system (like GObject), while OLE is a set of COM interfaces for embedding documents in other arbitrary documents. Like, if you want to put a spreadsheet into a Word document, OLE is the way you have to do that. Microsoft even built much of IE[0] on top of OLE to serve as its extension mechanism.

Oops, you are right about COM. I got them mixed up because I was thinking of the integration in WordPad.

> Mac apps are Mac native because Apple gives enough of a shit about being visually consistent that anyone using a cross-platform widget toolkit is going to look out of place. Windows abandoned the concept of a unified visual identity when Windows 8 decided to introduce an entirely new visual design built around an entirely new[1] widget toolkit, with no consideration of how you'd apply any of that to apps using USER.dll/Common Controls. As it stands today, Windows does not have a good answer to "what widget toolkit do I use to write my app", and even Microsoft's own software teams either write their own toolkits or just use Electron.

Mac apps are Mac native because the APIs are amazing and the ROI can be really really good. It takes so much effort to do the same from scratch, especially cross-platform, that, you're right, I can smell anything written in Qt (because the hitboxes and layout are off) or GTK (because the widget rendering is off).

With that said though, wxWidgets seems to translate EXTREMELY well to macOS, though last I used it, it didn't have good support for Mojave's dark mode. Maybe support is better nowadays. For example, Audacity appears to me as just a crammed Mac-native app rather than blatant use of a cross-platform toolkit, and wxPython used well can be completely mistaken for fully native.

Klonoar 3 hours ago | parent [-]

wxWidgets calls the underlying native controls directly; Qt uses it to inform how to render but still does its own thing, at least according to a discussion I had with a Qt engineer some years back.

(I am open to being corrected)

wxWidgets has properly supported dark mode for a bit now.