Storyteller lays out its Players, Embedded Clips, Cards, lists and Search for iPhone Duo's folded and unfolded displays, and while the device folds, unfolds and resizes. You don't need to change how you call Storyteller. This page covers how to build your app for iPhone Duo, how Storyteller works with your navigation, and what to expect.
Storyteller supports iPhone Duo from version 11.9.0. To get the full iPhone Duo layout, build your app with Xcode 27.1 (the iOS 27.1 SDK). Until then, iOS runs your app in compatibility mode on iPhone Duo, whichever Storyteller version it includes.
Storyteller 11.9.0 doesn't depend on any iOS 27.1-only APIs, so you don't need to raise your deployment target. Your app's own build SDK is what turns on the iPhone Duo layout.
With the key set, iPad and the unfolded iPhone Duo keep your app in a fixed-size window that the system scales to fit, and your app can't use Split View or Slide Over. On the unfolded iPhone Duo that window stays portrait-shaped, with an empty band at the top, even when the display is landscape-shaped.
If you place Embedded Clips (StorytellerClipsViewController or StorytellerClipsView) inside a UITabBarController or a UISplitViewController, Storyteller lays out beside the system navigation, including a tab bar that moves into the vertical bar. You don't need extra code, and Storyteller adjusts the insets of its own screens inside Embedded Clips.
Storyteller lists, Home and Cards are views that you lay out yourself, so place them beside your navigation as you would any other view.
Embedded Clips lays out its controls inside the safe area of StorytellerClipsViewController's view, so it can't see navigation that your app draws over it. Either lay StorytellerClipsViewController out beside your navigation, or set its additionalSafeAreaInsets to the part of your navigation that overlaps it:
finalclassEmbeddedClipsViewController:UIViewController{privateletembeddedClipsVC=StorytellerClipsViewController()overridefuncviewDidLoad(){super.viewDidLoad()addChild(embeddedClipsVC)view.addSubview(embeddedClipsVC.view)// Add Auto Layout constraints that fill the view here.embeddedClipsVC.didMove(toParent:self)// The app draws an 80 pt rail over the left edge of the Clips view.embeddedClipsVC.additionalSafeAreaInsets.left=80}}
Update the inset whenever your navigation changes size, appears or disappears. additionalSafeAreaInsets uses physical left and right edges, so set right for navigation on the right, including in right-to-left layouts. In SwiftUI, place StorytellerClipsView beside your navigation, for example in an HStack.
Story and Clip Players that you open from lists, Cards or Storyteller.shared cover the whole window, so they don't need this.
If you return your own screen from StorytellerDelegate.viewController(for:), Storyteller pushes it onto its navigation stack but doesn't change its insets. Next to a tab bar in the vertical bar, iOS can give that screen the bar's width as an extra side inset. If you see doubled spacing, adjust that screen's additionalSafeAreaInsets to cancel only the extra inset, and keep any insets the screen needs.
Story and Clip Players show a 9:16 column inside the safe area. Controls, captions and progress stay clear of the vertical bar and the rounded corners.
Unfolded
Players show a centred 9:16 column below the display's top corners, in either orientation. Grids and Search use the extra width.
Partially folded (book pose)
Players use the unfolded layout. iOS can show some sheets, such as the Story instructions, in one half of the display beside the fold.
Folding or unfolding
Playback continues while the Player resizes. Grids keep the same tiles in view while their width changes.
{"slug": "i-phone-duo", "page_title": "Supporting iPhone Duo", "page_url": "iPhoneDuo/", "canonical_url": "/ios/iPhoneDuo/", "markdown": "# Supporting iPhone Duo\n\nStoryteller lays out its Players, Embedded Clips, Cards, lists and Search for iPhone Duo's folded and unfolded displays, and while the device folds, unfolds and resizes. You don't need to change how you call Storyteller. This page covers how to build your app for iPhone Duo, how Storyteller works with your navigation, and what to expect.\n\n## Build Your App for iPhone Duo\n\nStoryteller supports iPhone Duo from version 11.9.0. To get the full iPhone Duo layout, build your app with Xcode 27.1 (the iOS 27.1 SDK). Until then, iOS runs your app in compatibility mode on iPhone Duo, whichever Storyteller version it includes.\n\nStoryteller 11.9.0 doesn't depend on any iOS 27.1-only APIs, so you don't need to raise your deployment target. Your app's own build SDK is what turns on the iPhone Duo layout.\n\n## If Your App Sets `UIRequiresFullScreen`\n\nIf your app's `Info.plist` sets `UIRequiresFullScreen` to `YES`, we recommend removing it to get the most out of iPhone Duo support. Apple deprecated the key in iPadOS 26; see [TN3192: Migrating your app from the deprecated UIRequiresFullScreen key](https://developer.apple.com/documentation/technotes/tn3192-migrating-your-app-from-the-deprecated-uirequiresfullscreen-key).\n\nWith the key set, iPad and the unfolded iPhone Duo keep your app in a fixed-size window that the system scales to fit, and your app can't use Split View or Slide Over. On the unfolded iPhone Duo that window stays portrait-shaped, with an empty band at the top, even when the display is landscape-shaped.\n\n## Work with Side Navigation\n\nOn iPhone Duo, the system can show your app's navigation in a vertical bar along the side of the display.\n\n### System Containers\n\nIf you place Embedded Clips (`StorytellerClipsViewController` or `StorytellerClipsView`) inside a `UITabBarController` or a `UISplitViewController`, Storyteller lays out beside the system navigation, including a tab bar that moves into the vertical bar. You don't need extra code, and Storyteller adjusts the insets of its own screens inside Embedded Clips.\n\n### Custom Side Navigation\n\nStoryteller lists, Home and Cards are views that you lay out yourself, so place them beside your navigation as you would any other view.\n\nEmbedded Clips lays out its controls inside the safe area of `StorytellerClipsViewController`'s view, so it can't see navigation that your app draws over it. Either lay `StorytellerClipsViewController` out beside your navigation, or set its `additionalSafeAreaInsets` to the part of your navigation that overlaps it:\n\n<!-- storyteller-swift-example: id=iphoneduo-01 target=sdk-ios context=declarations -->\n\n```swift\nfinal class EmbeddedClipsViewController: UIViewController {\n private let embeddedClipsVC = StorytellerClipsViewController()\n\n override func viewDidLoad() {\n super.viewDidLoad()\n\n addChild(embeddedClipsVC)\n view.addSubview(embeddedClipsVC.view)\n // Add Auto Layout constraints that fill the view here.\n embeddedClipsVC.didMove(toParent: self)\n\n // The app draws an 80 pt rail over the left edge of the Clips view.\n embeddedClipsVC.additionalSafeAreaInsets.left = 80\n }\n}\n```\n\nUpdate the inset whenever your navigation changes size, appears or disappears. `additionalSafeAreaInsets` uses physical left and right edges, so set `right` for navigation on the right, including in right-to-left layouts. In SwiftUI, place `StorytellerClipsView` beside your navigation, for example in an `HStack`.\n\nStory and Clip Players that you open from lists, Cards or `Storyteller.shared` cover the whole window, so they don't need this.\n\n### Custom Category Screens\n\nIf you return your own screen from [`StorytellerDelegate.viewController(for:)`](StorytellerDelegate.md#viewcontrollerfor-storytellercategory), Storyteller pushes it onto its navigation stack but doesn't change its insets. Next to a tab bar in the vertical bar, iOS can give that screen the bar's width as an extra side inset. If you see doubled spacing, adjust that screen's `additionalSafeAreaInsets` to cancel only the extra inset, and keep any insets the screen needs.\n\n## What to Expect\n\n| Pose or change | Behaviour |\n| --- | --- |\n| Folded | Story and Clip Players show a 9:16 column inside the safe area. Controls, captions and progress stay clear of the vertical bar and the rounded corners. |\n| Unfolded | Players show a centred 9:16 column below the display's top corners, in either orientation. Grids and Search use the extra width. |\n| Partially folded (book pose) | Players use the unfolded layout. iOS can show some sheets, such as the Story instructions, in one half of the display beside the fold. |\n| Folding or unfolding | Playback continues while the Player resizes. Grids keep the same tiles in view while their width changes. |\n| Split View or Slide Over | Storyteller lays out for your app's window. |\n\n## Known Limitations\n\n- Storyteller follows the safe area. It doesn't place content around the fold or the camera beyond that.\n- With Embedded Clips in landscape, the side safe areas around the Clip are left empty.\n\n## Test Your Integration\n\n1. Build your app with Xcode 27.1 and the Storyteller version you ship (11.9.0 or later).\n1. Check the folded display, both unfolded orientations, the book pose, and folding or unfolding while a Story or Clip plays.\n1. Check Embedded Clips beside your navigation, any custom category screens, Split View and Slide Over.\n1. Repeat your usual iPhone and iPad checks, especially if you removed `UIRequiresFullScreen`.\n\n## Related Resources\n\n- [Embedded Clips](EmbeddedClips.md#safe-area-inset-management)\n- [Handle Delegates and Callbacks](StorytellerDelegate.md)\n- [Apple: Preparing your app for iPhone Duo](https://developer.apple.com/documentation/technologyoverviews/preparing-your-app-for-iphone-duo)\n- [Apple: Designing for iPhone Duo](https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo)\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}