I'm happy to announce the public release of Ruckus , a Racket IDE for iPhone and iPad. Check it out and let me know what you think! Ruckus is open source and based on Noise . The frontend was coded almost entirely by Claude Code, with a lot of architecture guidance and code review from me. The project was on the back of my mind for a while, but I probably would never have started it were it not…
Update: Mystery solved! Pete Kazmier reached out over e-mail asking if I could share some packet captures of the problem. I sent them to him, and he figured out the issue. The Racket implementation was passing the wrong level to setsockopt , namely IPPROTO_TCP instead of SOL_SOCKET . The particular combination of the values of IPPROTO_TCP and SO_KEEPALIVE on macOS happens to map to a configuration…
A neat feature of the JVM is that, out of the box, you can send a running JVM process a SIGQUIT signal and it'll dump stack traces for all running threads to stdout . The output looks like this . It can be really handy when you're trying to debug a live system. Racket doesn't have this feature, but you can build something like it yourself by combining some of the introspection tools the runtime…
Following up on the previous post , another thing that's not well-documented when it comes to implementing widgets on iOS is how to share data between the widget and the main app. The widget is supposed to be small and efficient so loading all your models in there seems wrong (and the extension probably(?) can't even access the app's sandboxed database). The documentation mentions using network…
I'm currently adding widgets to Podcatcher and one issue I've run into that's not very well documented is how to trigger an App Intent — for example, to start playing a Podcast — from a widget, ensuring that the intent is performed in the app. There are two problems that need to be solved: The intent has to be a part of both the main app target and the widget extension target. How do we avoid…
I'm currently writing an Apple Watch counterpart app for Podcatcher . The Watch Connectivity framework that iOS apps use to communicate with watchOS apps offers a limited API for communication: you can either send untyped dictionaries or arbitrary byte strings between the two. In a large app, you want more structure than that framework offers. One approach you can take is to encode shared structs…
I recently added support for batch inserts to koyo and thought I'd make a quick post about it. Here's what it looks like to use this feature: (define ib (make-insert-batcher #:on-conflict '(do-nothing (ticker)) 'tickers '([isin "TEXT"] [ticker "TEXT"] [added_at "TIMESTAMPTZ"]))) (with-database-connection [conn db] (for ([(isin ticker added-at) (in-sequence datasource)]) (ib-push! ib conn isin…
If you listen to podcasts on iOS, chances are you've noticed an issue some apps have when displaying the playing episode's progress in the media center. For example, notice how in the video below, playback pauses at 0:39, then skips forward in real time to 0:45 when I hit resume, before the app finally resets the elapsed time back to 0:38. Pictured is one of the most popular iOS apps 1 for playing…
About a month ago, I added transcription support to Podcatcher . For example, here's a transcript of the latest episode of the Vergecast, and another one from AppStories. Years ago, I bought an M1 Mac Mini and, in the intervening time, I haven't done much with it besides keep it on my desk. So, I figured I'd put it to work for this purpose. I initially reached for Apple's Speech Framework, but…
Noise packages Racket & Chez Scheme boot files 1 for all the platforms it supports. Originally, that was just x86-64 and arm64 macOS, but when I added iOS support, that extended to include arm64 iOS. These boot files take up about 45MB for each arch+os pair and the way I originally distributed them was placing them all in a boot folder and adding them to the resources list for the core Noise…