●NATIVE — Rork Max reaches AR and LiDAR scanning, Metal-backed 3D, Dynamic Island, Siri Intents, HealthKit, NFC, App Clips, and on-device Core ML●IOS27 — iOS 27 Developer Beta 4 extends Siri AI to iPhone 15 Pro and 15 Pro Max plus the 16 and 17 lines, with noticeably faster responses than the first beta●DESIGN — Apple's own design kits for iOS, iPadOS, and macOS 27 are now available for Figma and Sketch, ready for when you lay out UI for the new OS●CANARY — Android 17, codenamed Cinnamon Bun, retires Developer Previews in favor of continuously updated Canary builds, which changes when you schedule testing●SPARK — Gemini Spark in Android 17 drives apps directly to automate multi-step errands like booking a ride or placing an order●SCALE — Rork raised $2.8M from a16z and now draws roughly 743,000 visits a month●NATIVE — Rork Max reaches AR and LiDAR scanning, Metal-backed 3D, Dynamic Island, Siri Intents, HealthKit, NFC, App Clips, and on-device Core ML●IOS27 — iOS 27 Developer Beta 4 extends Siri AI to iPhone 15 Pro and 15 Pro Max plus the 16 and 17 lines, with noticeably faster responses than the first beta●DESIGN — Apple's own design kits for iOS, iPadOS, and macOS 27 are now available for Figma and Sketch, ready for when you lay out UI for the new OS●CANARY — Android 17, codenamed Cinnamon Bun, retires Developer Previews in favor of continuously updated Canary builds, which changes when you schedule testing●SPARK — Gemini Spark in Android 17 drives apps directly to automate multi-step errands like booking a ride or placing an order●SCALE — Rork raised $2.8M from a16z and now draws roughly 743,000 visits a month
Showing Live Progress in the Dynamic Island from a Rork Max Swift App
How to add an ActivityKit Live Activity to a Swift app generated by Rork Max so progress shows in the Dynamic Island, plus the update-related pitfalls I hit in production.
I had a small timer app on the App Store, and the reviews kept circling the same complaint: "When I close the app I lose track of how much time is left." People wanted to glance at the remaining time from the home screen and the lock screen. The place that answers that wish is the Dynamic Island.
Rork Max generates native Swift, but a feature like a Live Activity, which pushes state outside the app, takes more than running the generated scaffold as-is. Adding the extension target, splitting the presentations, and managing the update budget all end up being hand work. Here is the order I used as an indie developer when I wired it into my own app.
The Dynamic Island Is Another Output for Live Activities
Let me clear up a common misconception first. The Dynamic Island is not a standalone API. When you define an ActivityKit Live Activity, that same state flows to both the lock screen banner and the Dynamic Island. Write one state model and you get two presentation surfaces for free.
Once that clicks, the rest is "draw the same data in different shapes." The flip side is that if you do not nail the state model first, both surfaces break together.
Define the State Model
The heart of a Live Activity is ActivityAttributes. Separate the unchanging attributes (a title) from the ContentState that changes moment to moment (the remaining time).
import ActivityKitimport SwiftUIstruct TimerAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { var endDate: Date var isPaused: Bool } var taskName: String}
Put only values that change on updates into ContentState. Anything fixed after launch, like taskName, lives outside. Drawing that line early keeps the update code thin.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦A three-step path to define ActivityAttributes and ContentState and launch a minimal Live Activity
✦Real DynamicIsland builder code for the compact, minimal, and expanded presentations
✦Seven production gotchas: the 8-hour cap, the update budget, and the APNs header for push updates
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
With the attributes in place, start the Activity from the app. Calling it from the view-model layer that Rork Max generated is the natural fit.
func startTimerActivity(name: String, minutes: Int) throws { guard ActivityAuthorizationInfo().areActivitiesEnabled else { throw ActivityError.notAuthorized } let attributes = TimerAttributes(taskName: name) let end = Date().addingTimeInterval(Double(minutes) * 60) let state = TimerAttributes.ContentState(endDate: end, isPaused: false) let activity = try Activity.request( attributes: attributes, content: .init(state: state, staleDate: end.addingTimeInterval(60)), pushType: nil ) print("started activity: \(activity.id)")}
Passing a staleDate lets the system mark the presentation as outdated once the end time passes. I set it one minute after the end so the display does not vanish at the exact zero-second mark.
Split the Three Dynamic Island Presentations
This is the core. In the Widget Extension you write an ActivityConfiguration and fill in compact, minimal, and expanded inside the dynamicIsland closure.
I fix the width of compactTrailing to stop the layout from jittering as the digit count changes. Pairing monospacedDigit() with frame(maxWidth:) keeps the island width stable even when it grows from 59 to 60. That behavior is hard to notice without a device.
Using Text(timerInterval:) lets the system advance the countdown without you sending an update every second. Hand continuous values like remaining time to that mechanism; it pays off as update-budget savings.
The Reality of State and Remote Updates
Update explicit "milestone" changes like pause and resume yourself.
func pause(_ activity: Activity<TimerAttributes>) async { var s = activity.content.state s.isPaused = true await activity.update(.init(state: s, staleDate: nil))}
Local updates are enough for that, but to reflect a server-side event (a delivery status change) you need push updates. Take the token from pushType: .token, send it to your own backend, and post to APNs with the apns-push-type: liveactivity header. Leave it as alert and nothing arrives, so check that first.
Pitfalls I Hit in Production
Even in a tiny app, several limits only showed up once it shipped. Here they are roughly in the order they bit me.
A Live Activity auto-ends after at most eight hours. Long timers need a separate restart path afterward.
Updates have a frequency budget; calling update every second gets throttled. Hand continuous values to Text(timerInterval:) and keep explicit updates to milestones.
Push updates require apns-push-type: liveactivity. I burned hours with it stuck on alert.
The simulator does not match the device for the Dynamic Island. Treat a real device as mandatory for verification.
Forget to set staleDate and a finished presentation lingers.
End with activity.end(...) and a dismissalPolicy: .immediate for instant removal, .after(date) to leave a tail.
Without NSSupportsLiveActivities set to YES in Info.plist it will not start at all. Freshly generated plists often lack it, so add it by hand.
In numbers, narrowing explicit updates to milestones cut my updates-per-hour by roughly 90% by feel, and the system throttling warnings disappeared.
What to Write Yourself, What to Delegate
In my own workflow I design the state model (ActivityAttributes) and the update logic myself, and I let Rork Max handle the initial lock-screen layout and color matching. The reason is simple: get the state design wrong and both surfaces break together, and fixing it later is expensive. Visual tweaks, by contrast, iterate fast between generation and hand edits, so they are worth drafting with AI.
The Dynamic Island is one of the few places to deliver value during the time the app is not open. Unlike ad revenue from AdMob, this works on the satisfaction of the experience itself. Just having the remaining time on the island softened the tone of my reviews. Small as it is, getting your first one shipped is well worth it.
I hope this helps with your implementation.
Share
Thank You for Reading
Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.