-
Modernize your UIKit app
Discover the latest updates to UIKit. Learn how to update your iPhone app layouts to work great when resized with iPhone Mirroring and on iPad. Explore new APIs for tab and navigation bars, find out how to prepare your app for new Apple Intelligence capabilities, and get introduced to a skill for your coding agent of choice that helps modernize your codebase.
Chapters
- 0:00 - Introduction
- 0:34 - App adaptivity
- 2:10 - Legacy API: App lifecycle
- 2:51 - Legacy API: Main screen
- 5:46 - Full-screen mode for games
- 6:17 - Legacy API: User interface idiom
- 7:06 - Legacy API: Interface orientation
- 7:55 - UIView Body protocols for motion & location
- 8:19 - Test your resizable iPhone app
- 9:18 - Tab bars and sidebars
- 10:52 - Navigation bars
- 12:37 - Menus
- 13:01 - Integrate with Apple Intelligence
- 14:07 - Agentic coding
- 15:32 - Next steps
Resources
- TN3208: Preparing your app’s launch screen to meet App Store requirements
- TN3210: Optimizing your app for iPhone Mirroring
- Make your UIKit app more flexible
- Adapting your app when traits change
- Transitioning to the UIKit scene-based life cycle
- Automatic trait tracking
- Human Interface Guidelines: Menus
Related Videos
WWDC26
- Explore advanced App Intents features for Siri and Apple Intelligence
- Get the most out of Device Hub
WWDC25
WWDC24
-
Search this video…
-
-
3:24 - Use local screen references
// Use local screen references // Access the correct screen through a windowScene let screen = window?.windowScene?.screen // Pass in local screen references func generateThumbnail(_ image: UIImage, screen: UIScreen) -> UIImage { // existing code, replacing main screen with local screen reference // ... } -
3:49 - Replace screen scale with displayScale
// Replace the screen's scale with trait collection's displayScale override func layoutSubviews() { super.layoutSubviews() // layoutSubviews will be called again automatically when displayScale changes let displayScale = traitCollection.displayScale // ... } -
4:36 - Register for trait changes
// Manually register for trait changes let displayScaleTrait: [UITrait] = [UITraitDisplayScale.self] registerForTraitChanges(displayScaleTrait) { (view: GalleryView, previousTraitCollection: UITraitCollection) in view.cache.invalidate() } -
5:19 - Monitor effective geometry changes
// UIWindowSceneDelegate func windowScene( _ windowScene: UIWindowScene, didUpdateEffectiveGeometry previousEffectiveGeometry: UIWindowScene.Geometry ) { let geometry = windowScene.effectiveGeometry let availableSpace = geometry.coordinateSpace.bounds // ... } -
5:35 - Check available space using view bounds
// Checking available space override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let availableSpace = view.bounds.size // ... } -
8:12 - Configure motion and location body
// Configure motion and heading bodies override func viewDidLoad() { super.viewDidLoad() motionManager.deviceMotionBody = view locationManager.headingBody = view } -
9:51 - Opt into sidebar layout
tabBarController.sidebar.preferredPlacement = .sidebar -
10:22 - Check sidebar availability
tabBarController.sidebar.isAvailable -
10:53 - Set prominent tab identifier
// Set the prominent tab let tabs = [ // ... ] let tabBarController = UITabBarController(tabs: tabs) tabBarController.prominentTabIdentifier = "cart" -
11:30 - Customize bar minimization behavior
// Customize bar minimization behavior override init( nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle? ) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) navigationItem.barMinimizationBehavior = .always navigationItem.barMinimizationSafeAreaAdjustment = .never } -
15:05 - Export Xcode skills for use in other tools
xcrun agent skills export
-
-
- 0:00 - Introduction
A modern UIKit app dynamically adjusts to the environment it runs in. iOS 27 introduces new requirements and APIs to help you get there. Discover new APIs in tab bars, navigation bars, and menus; Apple Intelligence support; and a new skill that helps an agent handle much of this modernization work automatically.
- 0:34 - App adaptivity
iPhone apps are now fully resizable in iPhone Mirroring on Mac and when running on iPad. Your app needs to dynamically adjust to any available scene size at runtime. The four areas to audit are scene lifecycle adoption, main screen references, user interface idiom checks, and interface orientation checks.
- 2:10 - Legacy API: App lifecycle
UIScene lifecycle is now required when building with the latest SDKs; apps without it will no longer launch. If you haven't migrated from app lifecycle yet, start here.
- 2:51 - Legacy API: Main screen
UIScreen.main always refers to the device's main screen, but in resizable environments your scene may be running on a different screen entirely. Replace it with screen references from the window scene, trait collections for scale, and effective geometry for available space.
- 5:46 - Full-screen mode for games
UIRequiresFullscreen is now honored on iPhone in resizable environments, enabling discrete resizing that respects your supported interface orientations so games always render at full quality.
- 6:17 - Legacy API: User interface idiom
The user interface idiom trait is no longer meaningful for layout. An iPhone app running on iPad stays in the phone idiom but is fully resizable. Use size classes instead.
- 7:06 - Legacy API: Interface orientation
Supported interface orientations are treated as a preference only and are ignored in resizable environments, including iPhone Mirroring which always reports portrait. Replace orientation checks with size classes.
- 7:55 - UIView Body protocols for motion & location
UIView now conforms to the new Body protocols from CoreMotion and CoreLocation in iOS 27, making it straightforward to keep motion and location data in the correct coordinate space regardless of interface orientation.
- 8:19 - Test your resizable iPhone app
Xcode 27's Device Hub app and Xcode Previews let you freely drag the edges of the simulator to test any screen size without needing multiple devices. Test with real devices for iPhone Mirroring and iPad.
- 9:18 - Tab bars and sidebars
iPhone apps can now opt into a sidebar layout by setting tabBarController.sidebar.preferredPlacement to .sidebar, with the system deciding when there's enough space to show it. Check tabBarController.sidebar.isAvailable to determine if the system can show the sidebar, and use tabBarController.prominentTabIdentifier to pin any tab so it stays visible even when the tab bar collapses during scroll.
- 10:52 - Navigation bars
Navigation bars can now slide away during scroll to give people more room. The system determines when this happens by default; override it with barMinimizationBehavior. The .automatic scroll edge effect style has new visuals; apps that previously overrode it to .soft should re-evaluate their design.
- 12:37 - Menus
Menu element images may no longer appear by default in some contexts like menu bars on iPadOS and macOS. Use preferredImageVisibility to override this behavior where needed.
- 13:01 - Integrate with Apple Intelligence
Menus automatically display an Ask Siri button when there's content relevant for Siri. If your app supports drag and drop, Siri can load resources from your drag handlers. Drag sessions can be initiated without a user gesture, so avoid triggering animations or presenting modal UI from sessionWillBegin.
- 14:07 - Agentic coding
Xcode 27's app modernization skill can automatically convert mainScreen calls, replace orientation checks with size class checks, and migrate your app to scene lifecycle. Skills can also be exported for use in other tools.
- 15:32 - Next steps
Build with the iOS 27 SDK, test in Device Hub and iPhone Mirroring on macOS 27, identify flexibility gaps in your app, and try the agentic modernization skill.