Hanyu Blog

Snapshotting SwiftUI Views on macOS (Three Approaches and an ImageRenderer Gotcha)

You have a SwiftUI view on macOS and you want to turn it into an NSImage for some downstream use: a tab preview, a thumbnail cache, an offline export… This post walks through the three pipeline designs, when each one fits, and where the sync-vs-async trade-off shows up.

Code Sample on Github

Snapshot Profiling Result

When Things Are No Longer Working: An Engineer's Approach to Speaking Up About Work Friction

Every engineer has a version of this story: It’s the third review round on the same proposal. The questions keep coming back — only that they aren’t really questions. They’re objections wearing question marks. The thread closes without a path forward, and the people on it aren’t aligned on what a path forward would even need to look like.

Each round had the same shape. Questions phrased to expose and object, not to contribute and converge. Skepticism with no alternative attached. “I don’t really see what this is solving.” “Aren’t these basically equivalent?” “I’m not convinced this is even the right problem.” “That’s a false choice.” Any one of these, in isolation, might be a fair technical concern. But stacked together week after week and round after round, they weren’t pushing for a path forward. They were a wall built one brick at a time.

It’s a painful moment and I had just lived through one. My usual instinct is to swallow it and keep moving, quieter than I started. But this time the cost was too high to absorb. I decided to speak up, and it saved a whole team of engineers and a critical project.

Measuring Best-Effort Features: How Good is 'Good Enough'

You finished your day of hard browsing and casually clicked ‘Clear My Data’ on your browser. Behind the scenes, 16 different systems spring into action—cookies, cache, browsing history, autofill data, site permissions… along with a cool fire animation. A few seconds later, the animation completes and you close the browser.

My analytics dashboard says: Clear Data Button Clicked: 1.

However, it doesn’t tell me something I really care as a developer: Did your data actually get cleared? Did one of those 16 systems fail silently? Did you wait 30 seconds staring at the spinner and give up? Did you trust that it worked, or did you immediately check your history to verify?

I have no idea. And that’s a problem.

Burning Data

2025 - Year In Review

I can’t remember where I saw my first Year in Review. It was probably Google’s, sometime around 2008, back when Google was a big part of the search and internet scene in China, and when I was still a primary school kid running around on summer afternoons, thinking nothing about jobs or life.

Fast forward to 2025, Year in Review is everywhere: Spotify, Instagram, LinkedIn…… even ChatGPT. I expected it to feel awkward, but OpenAI handled it surprisingly well.

Still Life with MacBook and Dog Bowl - ChatGPT, 2025

I’ve always found retrospectives useful, both for clarity and for growth. So here it is: my reflection on 2025.

A Walk through Foggy Midsummer Nights - Written at the End of a Job Hunt

In early 2025, as layoffs swept the tech industry and gen-AI loomed over everything, I left the role I had held for five years and took a leap into the unknown. I packed my life (and dog) into two suitcases and flew from downtown Toronto to the quiet countryside near London, where, with my new neighbors - swans, geese, and ducks (hint, hint), I went through a season of interviews, self-doubt, small triumphs, and quiet resilience. There were tears—many—and at times it felt like walking through a foggy forest at night, where the moon was hidden, but somehow, the moonlight remained.

On June 18th. 2025, I signed the offer that marked the end of this chapter. This is the story of the season of the job hunt.

IMG_7739.jpg

(Friendly Geese)