---
title: "TN3210: Optimizing your app for iPhone Mirroring"
framework: technotes
role: article
role_heading: Article
path: technotes/tn3210-optimizing-your-app-for-iphone-mirroring
---

# TN3210: Optimizing your app for iPhone Mirroring

Test your app and improve compatibility with iPhone Mirroring.

## Overview

Overview iPhone Mirroring lets people control their iPhone from a Mac using a trackpad or mouse. Most apps work without modification, because the system translates Mac input into the same indirect input events that iPad apps already receive from trackpads and mice. Standard UIKit and SwiftUI controls, system-provided sheets and popovers, scroll views, and built-in gesture recognizers continue to behave as people expect. However, some app behaviors require additional consideration. If your app uses custom gesture recognizers, custom sheets or popovers, or is a game that handles pointer input, these features may not respond correctly to a trackpad or mouse. If your app gates functionality behind biometric authentication, those requests fail by default because Face ID and Touch ID on the iPhone aren’t accessible from the Mac. This guide will help you test for and resolve each of these behaviors. Test your app during iPhone Mirroring Use iPhone Mirroring to validate your app’s behavior with a trackpad or mouse. Look for these specific issues: Indirect input: Verify that pinch, rotate, and scroll gestures work with a trackpad and scroll gestures work with a mouse. Sheet and popover dismissal: Verify that custom sheets and popovers dismiss with a trackpad scroll. Sheets should also dismiss with scroll-wheel mice, as they support UIScrollType.discrete. Game input: If your app is a game, verify that pointer input works correctly with a connected mouse or trackpad. Biometric authentication: Verify that biometric authentication works when iPhone Mirroring is active. note: iPhone Mirroring requires a Mac running macOS Sequoia 15 or later and an iPhone running iOS 18 or later. To enable it, see iPhone Mirroring: Use your iPhone from your Mac. Support indirect input iPhone Mirroring delivers trackpad and mouse events to your app using the same event types as on iPad — UIEvent.EventType.scroll for scrolling, and UIEvent.EventType.transform for pinch and rotate. Trackpad: pinch and rotate (UIEvent.EventType.transform). Trackpad: scroll (UIEvent.EventType.scroll). Produces .continuous scroll events. Magic Mouse: scroll (UIEvent.EventType.scroll). Produces .continuous scroll events. Scroll-wheel mouse: scroll (UIEvent.EventType.scroll). Produces .discrete scroll events. Check the indirect input opt-out key The UIApplicationSupportsIndirectInputEvents key is a compatibility affordance to ease the adoption of indirect input for a UIKit application. Add or update this key if your app meets either of the following conditions: UIApplicationSupportsIndirectInputEvents is set to NO in your Info.plist. Remove the key or change its value to YES. Your app targets iOS versions earlier than iOS 17 and the key is absent. Add the key with a value of YES to override the default value of NO. <key>UIApplicationSupportsIndirectInputEvents</key> <false/> For a full list of the indirect input behaviors this key controls, see UIApplicationSupportsIndirectInputEvents. Add built-in recognizers for indirect input event support Some indirect input events from trackpads and mice can only be recognized with subclasses of UIGestureRecognizer: Use UIPinchGestureRecognizer to handle UIEvent.EventType.transform from pinches on a trackpad. Use UIRotationGestureRecognizer to handle UIEvent.EventType.transform from rotations on a trackpad. Use UIPanGestureRecognizer and allowedScrollTypesMask to handle UIEvent.EventType.scroll from mouse scroll wheels or trackpads. Set allowedScrollTypesMask to choose whether you respond to scroll-wheel mice (.discrete), trackpad and Magic Mouse (.continuous), or both. If you have a custom UIGestureRecognizer subclass, you can keep it for direct touch and add a built-in recognizer alongside it for indirect input. For more information, watch Handle trackpad and mouse input. Verify that custom sheets and popovers dismiss correctly When testing, verify that your sheets and popovers dismiss correctly with a trackpad scroll or a mouse scroll wheel. If they don’t, it’s likely because you’re using a custom implementation. Consider using sheets provided by the system, which respond to trackpad and mouse scrolls automatically. Replace your custom implementation with UISheetPresentationController in UIKit or sheet(item:onDismiss:content:) in SwiftUI. If you can’t switch to the standard implementation, set allowedScrollTypesMask on your UIPanGestureRecognizer to .continuous for trackpad, or .all to also support a physical scroll wheel. let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan)) panGestureRecognizer.allowedScrollTypesMask = .continuous If your app runs on iPad, the indirect input support you add for iPhone Mirroring also improves its trackpad and mouse experience on iPad. You can verify this by testing on an iPad paired with an external mouse or trackpad. Use the Game Controller framework to handle pointer input in your game Games typically use responder-based event delivery rather than gesture recognizers. The pointer event types introduced for indirect input don’t support responder-based delivery. If you’re building a game, use the Game Controller framework to handle pointing devices instead of adding gesture recognizers, and use GCMouse for pointer support. Allow biometric authentication from a companion device When someone uses your app through iPhone Mirroring, biometric authentication requests fail by default because Face ID and Touch ID sensors on iPhone aren’t accessible from the Mac. The LAPolicy.deviceOwnerAuthenticationWithBiometrics policy only accepts biometric authentication on the iPhone itself, so it fails during iPhone Mirroring. Switch to LAPolicy.deviceOwnerAuthenticationWithBiometricsOrCompanion so people can accept authentication on the Mac or a paired Apple Watch. For more information, see LAPolicy. let context = LAContext() try await context.evaluatePolicy(     .deviceOwnerAuthenticationWithBiometricsOrCompanion,     localizedReason: reason ) You can also use the Keychain API to enforce biometric authentication. Apply a SecAccessControl object to your keychain item via kSecAttrAccessControl, then set the biometryAny and companion flags in SecAccessControlCreateFlags. For a complete walkthrough, see Restricting keychain item accessibility. When people authenticate using a companion device, the Secure Enclave on iPhone communicates directly and securely with the Secure Enclave on the companion device. For more information, see The Secure Enclave. Support drag and drop Support drag and drop so people can move data between iPhone and Mac while using your app through iPhone Mirroring. For design guidance, see Drag and drop in the Human Interface Guidelines. For implementation details, see Drag and drop. Revision History 2026-06-08 First published.

## See Also

### Latest

- [TN3211: Resolving SwiftUI source incompatibilities for State and ContentBuilder](technotes/tn3211-resolving-swiftui-source-incompatibilities-for-state-and-contentbuilder.md)
- [TN3212: Adopting gesture recognizers for Sidecar touch support](technotes/tn3212-adopting-gesture-recognizers-for-sidecar-touch-support.md)
- [TN3208: Preparing your app’s launch screen to meet App Store requirements](technotes/tn3208-preparing-your-apps-launch-screen-to-meet-app-store-requirements.md)
- [TN3205: Low-latency communication with RDMA over Thunderbolt](technotes/tn3205-low-latency-communication-with-rdma-over-thunderbolt.md)
- [TN3206: Updating Apple Pay certificates](technotes/tn3206-updating-apple-pay-certificates.md)
- [TN3179: Understanding local network privacy](technotes/tn3179-understanding-local-network-privacy.md)
- [TN3190: USB audio device design considerations](technotes/tn3190-usb-audio-device-design-considerations.md)
- [TN3194: Handling account deletions and revoking tokens for Sign in with Apple](technotes/tn3194-handling-account-deletions-and-revoking-tokens-for-sign-in-with-apple.md)
- [TN3193: Managing the on-device foundation model’s context window](technotes/tn3193-managing-the-on-device-foundation-model-s-context-window.md)
- [TN3115: Bluetooth State Restoration app relaunch rules](technotes/tn3115-bluetooth-state-restoration-app-relaunch-rules.md)
- [TN3192: Migrating your iPad app from the deprecated UIRequiresFullScreen key](technotes/tn3192-migrating-your-app-from-the-deprecated-uirequiresfullscreen-key.md)
- [TN3151: Choosing the right networking API](technotes/tn3151-choosing-the-right-networking-api.md)
- [TN3111: iOS Wi-Fi API overview](technotes/tn3111-ios-wifi-api-overview.md)
- [TN3191: IMAP extensions supported by Mail for iOS, iPadOS, and visionOS](technotes/tn3191-imap-extensions-supported-by-mail.md)
- [TN3134: Network Extension provider deployment](technotes/tn3134-network-extension-provider-deployment.md)
