Your Table View Cell Shows the Wrong Image. The Network Call Was Right — The Cell Just Wasn't.
UITableView and UICollectionView reuse cell views to stay fast, but an async image load or network callback that fires after a cell has been recycled writes into the wrong row. Here's why it happens, why it's so hard to reproduce, and the three fixes that actually close it.
ArraySlice Doesn't Give You a Piece of the Array. It Gives the Whole Array a Reason to Stay Alive.
ArraySlice and Substring look like lightweight, independent copies of part of a collection, but they hold a reference to the entire original storage. Here's the real memory-retention bug that causes, and how ~Escapable and Span are about to make it a compile-time guarantee instead of a docs warning.
Your Struct Looks Like It Copies When You Assign It. If It Wraps a Class, It Might Just Be Sharing.
Array gets copy-on-write for free because it checks isKnownUniquelyReferenced before every mutation. Build your own struct around a class-based buffer without that check, and 'independent copies' quietly become one shared object.
NSCache Looks Like a Dictionary With a Size Limit. It Isn't Promising You That.
NSCache's countLimit and totalCostLimit read like hard caps, but Apple's docs never promise them as guarantees, and eviction can happen for reasons you can't predict. Here's what NSCache actually contracts to do — and the one gotcha that breaks lookups silently.
Every Swift Task Already Has an ID. You Just Couldn't Read It Cheaply.
SE-0553 adds Task.currentID to Swift — a process-unique, never-reused task identifier that costs nanoseconds instead of the 15x-slower withUnsafeCurrentTask dance. Here's why that gap existed and what it unlocks for tracing and logging.
Swift's String.count Isn't O(1). It Walks the Whole String Every Time.
Swift's String.count looks like a free property access, but it's not — Unicode-correct grapheme cluster counting makes it O(n). Here's why Swift made that trade, where it actually costs you, and the isEmpty habit that sidesteps most of it.
You're Creating a New DateFormatter on Every Cell Scroll. That's the Lag You Can't Explain.
DateFormatter and ISO8601DateFormatter are expensive to initialize — locale and calendar setup included — and creating one inside a loop or a SwiftUI view body is a quiet, common performance bug. Here's the actual cost and the fix.
Date() Subtraction Lies to You About Elapsed Time. Swift's ContinuousClock Doesn't.
Measuring elapsed time with Date() subtraction quietly breaks when the system clock changes mid-measurement. Swift's ContinuousClock and Duration fix it — here's the difference and when it actually matters.
Your SwiftUI List Scrolls Like Mud. The Images Aren't the Problem — Decoding Them at Full Size Is.
Loading a photo into a 60pt thumbnail still decodes it at full resolution unless you tell iOS otherwise. Here's the actual fix: CGImageSourceCreateThumbnailAtIndex, why UIImage(data:) alone doesn't help, and how to downsample before a pixel ever hits the view.
AsyncImage Looks Like Free Image Loading. It Isn't Caching Anything.
AsyncImage handles the download and the loading spinner, so it feels like it's handling caching too. It isn't — scroll a list past a row and back, and it fetches the same image again. Here's why, and a caching wrapper that actually fixes it.
Embedded Swift Won't Let You Cheat. Turns Out That's a Feature.
Embedded Swift bans existentials, reflection, and the Objective-C runtime to fit Swift on microcontrollers. The restrictions it enforces are the same discipline that makes regular iOS code faster — and BrewLog's own networking layer breaks the rule on line one.
Your Background Task Isn't Broken. iOS Just Decided It Wasn't Worth Running.
BGTaskScheduler doesn't promise your task will run — it's a request, scored against battery, usage patterns, and network state. Here's how the budget actually works, how to test it without waiting three days, and how to design a sync that survives never being called.
InlineArray Just Got Hashable. Here's Why That Took a Whole Proposal.
SE-0543 was accepted on August 18, 2026, giving InlineArray a Hashable conformance. It sounds like a one-line addition — it wasn't. Here's what InlineArray actually is, why Hashable needed its own proposal, and where a fixed-size, stack-allocated array earns its keep over a regular Array.
Build Time Optimization for the Solo iOS Developer Running 5+ Apps
Day 30 of the 30-day iOS series. Real numbers, real DerivedData chaos, and the three things that actually move the needle on Xcode build times when you're maintaining multiple apps on one machine.
@Observable vs ObservableObject: What 1,000 Rows and a Redraw Counter Actually Showed Me
Day 13 of the 30-day iOS series. I built a redraw counter into BrewLog, put 1,000 rows in two identical lists side by side — one backed by @Observable, one by ObservableObject — and toggled a single favorite ten times. The row counts tied 10-10. The list counts didn't. Here's the real number, and exactly where it comes from.
Custom Liquid Glass Components: When to Leave the Defaults (and the Three Mistakes That Kill Your Frame Rate)
glassEffect(.regular, in:) with a custom shape, two glass blobs that morph into each other with glassEffectID, and the three things that turn buttery Liquid Glass into a stutter machine. Built on a real iPhone 17 Pro simulator, with the TDD seam that keeps the decision testable even though the render isn't.