Work with the grain of the framework by writing your own property wrappers.| Shadowfacts
Use focused values for conveying information up the view hierarchy based on the currently-focused view.| Shadowfacts
I’ve been watching a lot of woodworking YouTube lately. The trope of software engineers taking up woodworking as a hobby is well-worn, and the consensus seems to be that its parallels to building software—combined with the physical tangibility—are attractive after spending so much time staring at a computer screen. But I don’t believe that explanation wholly captures the phenomenon.| Shadowfacts
Welcome to version 7 of my website. What started as a rewrite of the backend last fall has since snowballed into a complete redesign of the frontend as well (if you’re using an RSS reader, check out the actual site). The previous design dates back to the fall of 2019 and, after doing a bunch of work to rewrite the backend, rebuilding the exact same frontend again wasn’t an attractive prospect.| Shadowfacts
I do not pretend to know fully understand how this came to be the case, or what to do about it, but I am increasingly of the opinion that the single most pressing problem of the American polity is that of amorality. Not immorality, amorality. It is not the case that we collectively believe what we are doing to be wrong—or believe it to be right; we simply do not care.| Shadowfacts
When SwiftUI was announced in 2019 (oh boy, more than 5 years ago), one of the big things that the Apple engineers emphasized was that a SwiftUI View is not like a UIKit/AppKit view. As Apple was at pains to note, SwiftUI may evaluate the body property of a View arbitrarily often. It’s easy to miss an important consequence this has, though: your View will also be initialized arbitrarily often. This is why SwiftUI views are supposed to be structs which are simple value types and can be stack...| Shadowfacts
Last time, I wrote about how to parse HTML and convert it to NSAttributedStrings quickly. Unfortunately, in the time since then, it’s gotten slower. It’s still a good deal faster than it was before all that work, mind you. At fault is not any of the optimizations I discussed last time, fortunately. Rather, to get the correct behavior across a whole slew of edge cases, there was more work that needed to be done.| Shadowfacts
The urge to overengineer something recently befell me, and the target of that urge was the way Tusker handles HTML parsing. Mastodon provides the content of posts (and profile descriptions, and some other things) as HTML, which means that, in order to display them properly, you need to parse the HTML, a notoriously straightforward and easy task. For a long time, the approach I took was to use SwiftSoup to parse the HTML and then walk the resulting node tree to build up a big NSAttributedStrin...| Shadowfacts
Passkeys are a replacement for passwords that use public/private cryptographic key pairs for login in a way that can be more user-friendly and resistant to a number of kinds of attacks. Let’s implement account registration and login with passkeys in a simple Phoenix web app.| Shadowfacts
Preferences are a powerful, and underappreciated, tool for data flow in SwiftUI.| Shadowfacts