Live Activities Development for iOS—End-to-End
Imagine a delivery app showing order progress right on the lock screen—users never open the phone, they just see the courier is around the corner. We've implemented such solutions for several clients and know every nuance. One of these solutions boosted retention by 20% in the first month after launch. Order professional Live Activities development from us.
Live Activities is a feature from iOS 16.1+ that lets your app display dynamic content on the lock screen and in Dynamic Island (starting with iPhone 14 Pro). Taxi en route—progress-bar updates in real time. Match ongoing—score in Dynamic Island without unlocking. According to Apple, users interact with Live Activities on average 3 times more often than with regular notifications (Human Interface Guidelines, Apple).
What Live Activities Bring to Your Business?
Competition for user attention is fierce. Live Activities is the only way to stay visible without interrupting other tasks. According to our data, implementing Live Activities increases retention by 20–30%. Ride-hailing, delivery, fitness trackers, sports apps are already using this. If you're not using Live Activities—you're missing out on your audience.
How We Implement Live Activities: Stack and Examples
We use Swift 5.9+, SwiftUI, Combine. The main framework is ActivityKit. The architecture rests on three components: ActivityAttributes (static data), ContentState (dynamic data), and SwiftUI Views for the three presentation states.
struct DeliveryAttributes: ActivityAttributes {
// Static data — never changes during activity lifetime
let orderId: String
let restaurantName: String
struct ContentState: Codable, Hashable {
// Dynamic data — updates over time
var status: DeliveryStatus
var estimatedMinutes: Int
var courierLocation: CLLocationCoordinate2D?
}
}
let attributes = DeliveryAttributes(orderId: "1234", restaurantName: "Pizza South")
let state = DeliveryAttributes.ContentState(status: .preparing, estimatedMinutes: 30)
let content = ActivityContent(state: state, staleDate: Date().addingTimeInterval(600))
let activity = try Activity.request(
attributes: attributes,
content: content,
pushType: .token
)
How to Update the Activity via Push?
The most reliable method is ActivityKit Push Notifications (not regular APNs). Push payload:
{
"aps": {
"timestamp": 1698765432,
"event": "update",
"content-state": {
"status": "in_delivery",
"estimatedMinutes": 12
}
}
}
Get the push token for Live Activity via activity.pushTokenUpdates AsyncSequence. Token updates can occur, so listen to the stream:
Task {
for await tokenData in activity.pushTokenUpdates {
let token = tokenData.map { String(format: "%02x", $0) }.joined()
await sendTokenToServer(token)
}
}
SwiftUI Views for All Zones
struct DeliveryLiveActivityView: View {
let context: ActivityViewContext<DeliveryAttributes>
var body: some View {
HStack {
Image(systemName: statusIcon(context.state.status))
VStack(alignment: .leading) {
Text(context.attributes.restaurantName)
.font(.headline)
Text("\(context.state.estimatedMinutes) min")
}
Spacer()
DeliveryProgressView(status: context.state.status)
}
.padding()
}
}
DynamicIsland builder for Dynamic Island:
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
Image(systemName: "bicycle")
}
DynamicIslandExpandedRegion(.trailing) {
Text("\(context.state.estimatedMinutes) min")
}
DynamicIslandExpandedRegion(.bottom) {
Text("Courier: \(courierName)")
}
} compactLeading: {
Image(systemName: "bicycle")
} compactTrailing: {
Text("\(context.state.estimatedMinutes)m")
} minimal: {
Image(systemName: "bicycle")
}
Why Live Activities Are Harder Than They Seem?
Under the hood, ActivityKit is a complex resource management system. The size of ContentState in push must not exceed 4 KB. If you exceed it, the notification is discarded. We encountered this in a delivery project: we tried to pass the full courier track (100+ points)—push didn't work. The solution: pass only the current position, store history locally.
Another challenge is the stale state. If you don't update the activity on time, it "freezes" with outdated data. You need to set staleDate and update on trigger. In one case, we forgot to handle order closure—the activity lingered for a day. Now this is automated.
What Mistakes Should You Avoid When Implementing?
| Typical Mistake | Consequences | How to Avoid |
|---|---|---|
| Payload too large (>4KB) | Push not delivered | Compress data, use static in Attributes |
| Updating from background without push | Doesn't work, activity freezes | Use ActivityKit Push Notifications |
| Ignoring stale state | Shows outdated data | Set staleDate and update accordingly |
| Incorrect push token setup | Notifications don't arrive | Subscribe to pushTokenUpdates and send token to server |
Our Work Process: From Idea to Publication
| Phase | Actions | Result |
|---|---|---|
| Analysis | Study your scenario, determine data types and UI | Technical specification |
| Design | Architect ActivityAttributes and ContentState | Data diagram |
| Implementation | Create SwiftUI views, integrate ActivityKit, set up push | Working prototype |
| Testing | Verify on real devices, simulate scenarios | Testing report |
| Deployment | Prepare metadata, publish to App Store | Live Activity in production |
What’s Included in the Deliverable
- Source code in Swift 5.9+ with comments
- SwiftUI views for Lock Screen and Dynamic Island
- Server-side for sending push notifications (if required)
- Documentation for maintenance and updates
- Training for your developer (optional)
Important Constraints to Keep in Mind
-
ContentStatesize—no more than 4 KB in push payload. - App must be in foreground to start an activity (from recent iOS versions, you can check
ActivityAuthorizationInfo().areActivitiesEnabled). - Dynamic Island is available only on physical iPhone 14 Pro/Pro Max+.
- Simulator supports Live Activities from a corresponding iOS version.
We guarantee quality: every activity passes review against StoreKit and Human Interface Guidelines standards. Get a free project estimate—contact us.
Timelines and Pricing
Basic implementation with push updates—from 3 to 5 business days. Complex UI and server-side logic may extend the timeline to 2 weeks. Pricing is calculated individually, but we always provide an accurate estimate before work begins.
Get a consultation—reach out to discuss your project.







