Last weekend, I attended an App Accelerator event hosted by Apple in Beijing. The event focused primarily on app development, operations, and business models in the age of AI. Most of the attendees were managers at tech companies or app developers. Throughout the event, enthusiasm for AI was high, with people exchanging their own perspectives on AI and sharing how they were putting it to use. I learned a great deal from those conversations.
After the event, I had dinner with a friend who works in a traditional industry. He knew almost nothing about AI. As an emerging concept, it was something he wanted to understand, but he had never really seen what tangible benefits AI could bring to his business. During dinner, he received a phone call: a client needed a proposal revised immediately. It was the weekend, and even if he assigned the task right away, it would have been difficult to get it done within a short period of time. After hearing roughly what was needed, I realized that the task happened to fall squarely within AI’s comfort zone. So I pulled out my phone and had AI handle it for him. A few minutes later, the result was ready.
He was impressed not only by how quickly AI completed the task, but also by the quality of the result. And at his company, there happened to be a team of five or six people whose work largely consisted of handling similar tasks.
He immediately started asking me for more details and calculating how much headcount he could reduce, and how much money he could save, if the company adopted AI.
The speed of that shift caught me somewhat off guard. I immediately brought up another possibility: if AI can accomplish existing work at a much lower cost, could those newly available capabilities also be used to pursue opportunities that had previously been too expensive to explore? Cutting costs is certainly one of AI’s most obvious benefits, but generating new revenue is just as much a field where AI can make a difference.
On the way home, I kept thinking about those five or six people. Right now they are probably enjoying a quiet weekend, unaware that their jobs had just been repriced over the course of a single meal. And what prompted that repricing was a demo I ran a few minutes earlier.
The next time I find myself in a similar situation, I will probably still pull out my phone and show someone what AI can do. But I think I should at least remember this: what takes just a few keystrokes on one side of the screen may mean something very different on the other.
Recent Recommendations
Why Swift is introducing a warning for weak captures within nested closures
Weak captures are an important memory management mechanism in Swift. Historically, if a weak capture is used only in the inner closure of a nested closure, the Swift compiler may implicitly insert a strong capture in the parent closure. Even though this behavior can lead to a retain cycle in certain situations, the compiler previously provided no warning. Starting with Swift 6.4, the compiler will issue a warning when it detects a mismatch between a weak capture in an inner closure and an implicit strong capture in the outer closure.
John Sundell explains this change and offers several solutions: depending on the situation, explicitly declare the capture semantics in the parent closure; if both closures need to manage their lifetimes independently, declare the appropriate capture semantics for each one. This may be a small update to the Swift compiler, but it helps developers express ownership relationships between nested closures that could otherwise be easily overlooked.
Running iOS Background Tasks Reliably
BGTaskScheduler has never been cron for iOS. When a background task actually runs depends on system scheduling, device state, energy budgets, and how users interact with the app. Irving Popovetsky used telemetry from a real device to observe background task behavior over an extended period and shared a number of lessons learned along the way: frequently resubmitting tasks in an attempt to improve reliability can actually keep pushing back a task that was close to getting an execution opportunity; user behavior and system conditions such as force quitting, not opening the app for a long time, Low Power Mode, and device reboots can all affect whether background tasks get a chance to run; and a task running later than requested does not necessarily mean that scheduling has gone wrong.
For background tasks, developers should not try to precisely schedule execution. Instead, the goal should be to make the most efficient and correct use of the opportunities the system chooses to provide.
The Memory Remains: TipKit in a Shipping App
TipKit is easy to learn, but using it well in a real project is much harder. The real challenges are knowing when tips should not appear, avoiding disruptions to the user experience, and ensuring that the underlying logic remains testable and maintainable. Wesley Matlock shares lessons from using TipKit in a shipping app: @Parameter is better suited to current state that can be recomputed at any time, while Tips.Event is appropriate for historical behavior that cannot be reconstructed from current state; every tip should avoid periods when onboarding or other launch UI may still appear; and because Tips.configure only takes effect once per process, initialization order, debug tooling, and test environments all need to be designed around that constraint.
The essence of TipKit lies not in its visual presentation, but in its internal logic. It helps developers declaratively describe the rules that determine when tips should appear, while leaving the actual presentation entirely customizable. We can think of TipKit as a rules engine that determines whether a tip should be displayed; how those rules are visualized is up to the developer. For more discussion from this perspective, see Mastering TipKit: Advanced.
Building an accessible calendar chart with Swift Charts
Matthaus Woolard demonstrates how to build a calendar chart similar to GitHub Contributions using Swift Charts. The more interesting part of the article, however, is its approach to accessibility. Because the same weekday across different weeks shares a normalized x value, VoiceOver groups an entire column of data together instead of allowing users to navigate day by day. The author solves this by using accessibilityChildren to construct a separate accessibility hierarchy for the plot area that corresponds to the visual layout.
Swift Charts Beyond the Basics, co-authored by Matthaus Woolard and Natalia Panferova, was officially released last week. For developers looking to create advanced data visualizations with Swift Charts, it is a rare and valuable advanced guide.
Mac App Direct Distribution, DMG Signing & Notarization Guide
Compared with publishing through the Mac App Store, distributing a macOS app directly requires developers to handle more of the release process themselves: Developer ID signing, DMG creation, notarization, stapling, and final Gatekeeper verification. A problem at any one of these stages can prevent users from installing the app successfully. Stewart Lynch walks through the complete release workflow, from creating an Xcode Archive and building the DMG to final signing, notarization, and verification.
Consuming SKIE Flows in SwiftUI
In projects that use Kotlin Multiplatform (KMP) to share business logic while building native UIs with SwiftUI, making Kotlin APIs integrate naturally into the Swift ecosystem has always been an important challenge. SKIE (Swift Kotlin Interface Enhancer) was created to improve this interoperability experience. It can convert Kotlin Flow into Swift AsyncSequence, allowing Swift code to consume data using familiar Swift Concurrency patterns.
Gustavo Fão Valvassori introduces a set of SwiftUI-specific APIs provided by SKIE: besides consuming data directly from an AsyncSequence inside .task, developers can use .collect to bind Flow updates to SwiftUI state, or use the Observing wrapper to hide state management and let the latest value from a Kotlin StateFlow directly participate in building the View.
Sarunw’s How-to Series Returns
Sarunw’s blog has long been an excellent resource for developers looking for practical tips on Apple platform development. However, the blog stopped receiving updates at the end of 2023. Last week, Sarunw resumed writing and published several new articles in his How-to series within just one week. It’s great to see an excellent content creator return after nearly three years away.
Tool
JindoKit: Preview Dynamic Island presentations in your app
WidgetKit’s Live Activity previews are primarily intended for development and debugging within Xcode. For apps that allow users to choose themes or customize displayed content, however, the system does not provide an equivalent way to preview those presentations directly inside the app.
Developed by Kyle Ye, JindoKit brings WidgetKit-style Dynamic Island APIs into regular SwiftUI Views, allowing apps to directly preview expanded, compact, and minimal Dynamic Island presentations. Since its API closely mirrors WidgetKit’s structure, developers can organize content for each region in a similar way and reuse related views and data between the app’s configuration UI and its WidgetKit Extension. For more information, see the author’s introductory article: Preview Dynamic Island presentations in your app with JindoKit.