Flutter Performance Deep Dive: 60fps on Low-End Android Devices
Most Flutter apps perform beautifully on flagship phones. The real test is a ₹8,000 Android device with 2GB RAM. Here's how we consistently hit 60fps where other teams give up.
A developer-focused breakdown of iOS 16's most impactful features, including lock screen widgets, Live Activities, passkeys, and SwiftUI improvements with Swift code examples.
Priya Nair
Senior Mobile Architect
iOS 16 is the most significant iPhone software update since the original iPhone OS, bringing fundamental changes to how users interact with their devices. For developers, it introduces new APIs that open up entirely new categories of app experiences. This guide covers the features that matter most and provides code examples to get you started. Our iPhone app development team has already shipped several of these patterns into production apps.
iOS 16 finally allows third-party widgets on the lock screen. This is a major opportunity for apps that surface time-sensitive information — fitness trackers, weather apps, calendars, and news readers. Widgets use the WidgetKit framework and support multiple sizes: small (accessoryCircular), medium (accessoryRectangular), and large (accessoryInline).
import WidgetKit
import SwiftUI
struct FitnessWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "FitnessWidget", provider: FitnessProvider()) { entry in
FitnessWidgetView(entry: entry)
}
.configurationDisplayName("Activity Rings")
.description("Track your daily activity on the lock screen.")
.supportedFamilies([
.accessoryCircular,
.accessoryRectangular,
.accessoryInline
])
}
}
struct FitnessWidgetView: View {
let entry: FitnessEntry
var body: some View {
switch widgetFamily {
case .accessoryCircular:
ZStack {
AccessoryWidgetBackground()
Image(systemName: "figure.run")
}
case .accessoryRectangular:
VStack(alignment: .leading) {
Text("Move: \(entry.moveGoal)%")
Text("Exercise: \(entry.exerciseMinutes) min")
Text("Stand: \(entry.standHours) hrs")
}
case .accessoryInline:
Text("Move \(entry.moveGoal)% | Exercise \(entry.exerciseMinutes)m | Stand \(entry.standHours)h")
}
}
}
Lock screen widgets are limited to text, SF Symbols, and simple shapes — no full-color images. This constraint ensures they remain readable at a glance and do not drain battery.
Live Activities replace the static notification banner with a persistent, interactive element on the lock screen. On iPhone 14 Pro and later, they also appear in the Dynamic Island — the pill-shaped cutout that replaces the notch. This is ideal for ride-sharing, food delivery, fitness tracking, and timer apps.
Live Activities use the ActivityKit framework. You start an activity from your app, update it with new data, and end it when the task is complete. The system handles rendering and updates. Building this well requires engineers comfortable with its concurrency model — reach out if you need to hire Swift developers who've shipped Live Activities before.
import ActivityKit
struct DeliveryActivityAttributes: ActivityAttributes {
struct ContentState: Codable, Hashable {
var driverName: String
var estimatedArrival: Date
var distanceRemaining: Double
}
var orderNumber: String
}
// Start a Live Activity
func startDeliveryActivity(orderNumber: String) {
let attributes = DeliveryActivityAttributes(orderNumber: orderNumber)
let initialState = DeliveryActivityAttributes.ContentState(
driverName: "Alex",
estimatedArrival: Date().addingTimeInterval(1800),
distanceRemaining: 2.5
)
do {
let activity = try Activity.request(
attributes: attributes,
contentState: initialState
)
print("Started Live Activity: \(activity.id)")
} catch {
print("Error: \(error)")
}
}
// Update the activity
func updateDeliveryActivity(activity: Activity) {
let updatedState = DeliveryActivityAttributes.ContentState(
driverName: "Alex",
estimatedArrival: Date().addingTimeInterval(600),
distanceRemaining: 0.8
)
Task {
await activity.update(using: updatedState)
}
}
iOS 16 introduces passkeys — a password replacement built on the FIDO2/WebAuthn standard. Passkeys are stored in iCloud Keychain and sync across devices. They are phishing-resistant because the credential is bound to the originating domain. When a user signs in, the app requests a cryptographic challenge from the server, the device signs it with the private key, and the server verifies with the public key.
Implement passkeys using the AuthenticationServices framework. Register a new credential with ASAuthorizationPlatformPublicKeyCredentialProvider, and authenticate with ASAuthorizationPlatformPublicKeyCredentialAssertion. Support both passkeys and traditional sign-in during the transition period.
iOS 16 introduces two significant notification changes. First, notifications now appear at the bottom of the lock screen by default, with the option to switch to a list view. Second, apps can now send notifications that update in place — the system replaces the existing notification rather than stacking new ones. This is critical for delivery tracking, ride-sharing, and any app that sends frequent status updates.
Use the threadIdentifier and interruptionLevel properties to control how notifications are grouped and how urgently they interrupt the user. The interruptionLevel can be passive, active, timeSensitive, or critical.
SwiftUI gains major new capabilities in iOS 16. The NavigationStack replaces NavigationView with a programmatic, path-based navigation model. Multi-column navigation is now supported with NavigationSplitView. The new Grid view enables complex layouts without nested HStacks and VStacks. Charts framework provides native data visualization. And the new ShareLink simplifies sharing content. These updates make SwiftUI a stronger default choice — something our Swift development engineers weigh on every new project.
// NavigationStack — the new programmatic navigation
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List {
NavigationLink("Profile", value: Route.profile)
NavigationLink("Settings", value: Route.settings)
}
.navigationDestination(for: Route.self) { route in
switch route {
case .profile: ProfileView()
case .settings: SettingsView()
}
}
}
}
}
// Charts framework
import Charts
struct SalesChart: View {
let data: [SalesData]
var body: some View {
Chart(data) { item in
BarMark(
x: .value("Month", item.month),
y: .value("Sales", item.revenue)
)
.foregroundStyle(by: .value("Category", item.category))
}
}
}
iOS 16 changes the Photos picker behavior. The new PHPickerViewController gives users fine-grained control — they can select specific photos to share with your app, rather than granting full library access. This is a privacy win but requires you to update your photo selection flow. Use the PhotosPicker view modifier in SwiftUI for the simplest integration.
Additionally, iOS 16 introduces the ability to edit and delete messages in iMessage, and to recover recently deleted messages. While this does not directly affect third-party apps, it signals Apple's direction toward giving users more control over their data — expect similar privacy enhancements in future releases.
Tags
Continue Reading
Most Flutter apps perform beautifully on flagship phones. The real test is a ₹8,000 Android device with 2GB RAM. Here's how we consistently hit 60fps where other teams give up.
SwiftUI has matured significantly, but UIKit isn't going anywhere. The choice depends on your team, your timeline, and what you're building. Here's a practical guide for making the right call.
The New Architecture — JSI, Fabric, TurboModules — is now stable and the default. Here's what actually changes, what you need to migrate, and whether the performance gains are real.
From AI agents to mobile apps — iMOBDEV builds what your business needs.