{"$schema": "https://raw.githubusercontent.com/guitaripod/wwdc-sessions/master/schema/transcript.schema.json", "id": "wwdc2026-219", "language": "eng", "source": "https://developer.apple.com/videos/play/wwdc2026/219", "wordCount": 2752, "segments": [{"start": 7.0, "text": "Hi!"}, {"start": 8.0, "text": "My name is Josh, and I'm a Software Engineer"}, {"start": 11.0, "text": "on the Accessibility team."}, {"start": 13.0, "text": "Today, I'm going to talk about how to make your long form text"}, {"start": 17.0, "text": "or reading app accessible to everyone on Apple platforms."}, {"start": 23.0, "text": "Reading long-form content is fundamentally different from navigating UI:"}, {"start": 27.0, "text": "it's about moving fluidly through text,"}, {"start": 30.0, "text": "not just moving between UI elements like controls."}, {"start": 34.0, "text": "Apple's frameworks come built-in with accessible text in mind."}, {"start": 39.0, "text": "But, there's more work you can do as a developer to enrich"}, {"start": 44.0, "text": "and extend the accessibility experience with long form text."}, {"start": 49.0, "text": "Today, I'm going to share some best practices and techniques"}, {"start": 53.0, "text": "for you to consider as you build your long-form content."}, {"start": 58.0, "text": "First, I'll talk about what characteristics make up a great reading experience"}, {"start": 63.0, "text": "for someone using VoiceOver, or another assistive technology."}, {"start": 67.0, "text": "Then, I'll show how you can use"}, {"start": 70.0, "text": "and extend views from UIKit and SwiftUI"}, {"start": 73.0, "text": "using rich APIs designed specifically for the reading experience."}, {"start": 78.0, "text": "And last, I'll cover how you can make custom text in your app accessible"}, {"start": 82.0, "text": "to VoiceOver, Speak Screen, or the Accessibility Reader."}, {"start": 87.0, "text": "Starting off, I'll discuss what makes a great accessible experience"}, {"start": 91.0, "text": "in an app that displays long form content."}, {"start": 94.0, "text": "Today, I want to build an app so that I can share recommendations and travel tips"}, {"start": 100.0, "text": "for one of my favorite cities: Chicago."}, {"start": 104.0, "text": "My app has paginated content, with multiple paragraphs and text"}, {"start": 107.0, "text": "that wraps across multiple lines."}, {"start": 111.0, "text": "I want to make sure that anyone using an assistive technology"}, {"start": 115.0, "text": "has a great experience with this app."}, {"start": 118.0, "text": "In this session, I'll focus on two popular"}, {"start": 121.0, "text": "assistive technologies built into Apple platforms:"}, {"start": 124.0, "text": "VoiceOver and Speak Screen."}, {"start": 127.0, "text": "VoiceOver is Apple's built-in screen reader,"}, {"start": 130.0, "text": "designed for individuals who are blind or low vision."}, {"start": 134.0, "text": "When I activate it, I can hear whatever is highlighted by the cursor."}, {"start": 139.0, "text": "Morning."}, {"start": 140.0, "text": "Heading."}, {"start": 141.0, "text": "We started out our morning in Lincoln Park,"}, {"start": 144.0, "text": "strolling through the trails and admiring the views of the Chicago skyline."}, {"start": 151.0, "text": "Speak Screen is designed to read aloud all of the content on a given page,"}, {"start": 156.0, "text": "from top to bottom, highlighting while it is speaking."}, {"start": 160.0, "text": "When turned on, I can initiate it by dragging down with two fingers"}, {"start": 164.0, "text": "from the top of the screen."}, {"start": 167.0, "text": "Midday."}, {"start": 168.0, "text": "At lunchtime, we walked along the Chicago river."}, {"start": 171.0, "text": "The river-front path gave us great views of the city's magnificent architecture."}, {"start": 176.0, "text": "Our favourite view was from the middle of the DuSable Bridge,"}, {"start": 179.0, "text": "where we could look straight down the river."}, {"start": 183.0, "text": "Keeping these technologies in mind,"}, {"start": 186.0, "text": "I've made three goals to improve the interaction"}, {"start": 188.0, "text": "between those features and my app."}, {"start": 191.0, "text": "Specifically, I want to make sure my app offers granular text navigation,"}, {"start": 196.0, "text": "so that VoiceOver and Speak Screen can fluidly move through the text."}, {"start": 201.0, "text": "I also want to make sure I'm developing a continuous reading experience,"}, {"start": 205.0, "text": "so someone using an assistive technology doesn't encounter any interruptions."}, {"start": 210.0, "text": "Lastly, I want to make sure my app provides comprehensive text selection."}, {"start": 217.0, "text": "I'm going to focus on these main goals during the rest of this video,"}, {"start": 221.0, "text": "and make sure that my travel app satisfies them all."}, {"start": 226.0, "text": "Apple's frameworks provide many text components"}, {"start": 228.0, "text": "that are accessible right out of the box,"}, {"start": 231.0, "text": "so now I'll focus on what those are, what they provide you,"}, {"start": 235.0, "text": "and how you can extend them with additional functionality."}, {"start": 239.0, "text": "Both UIKit and SwiftUI provide accessible text views, that allow for line, word,"}, {"start": 245.0, "text": "and character navigation with VoiceOver and Speak Screen,"}, {"start": 248.0, "text": "alongside accessible text selection."}, {"start": 252.0, "text": "You might already be familiar with UIAccessibilityReadingContent,"}, {"start": 256.0, "text": "which is a great way to make full page content accessible."}, {"start": 259.0, "text": "While I'm not going to focus on that protocol,"}, {"start": 262.0, "text": "you can still use and adopt it on top of everything I'll discuss today."}, {"start": 267.0, "text": "To learn more, check out \"Creating an Accessible Reading Experience\"."}, {"start": 273.0, "text": "Today, I'm going to focus on UITextInput,"}, {"start": 276.0, "text": "a higher fidelity protocol that native text views use,"}, {"start": 279.0, "text": "and one that you can adopt as well on custom views."}, {"start": 284.0, "text": "Standard text views across the system adopt the UITextInput protocol."}, {"start": 289.0, "text": "With UIKit using UITextView on iOS will give you a rich text experience"}, {"start": 294.0, "text": "from the get go,"}, {"start": 295.0, "text": "as will TextEditor in SwiftUI."}, {"start": 298.0, "text": "You can even use a simple SwiftUI Text view with selection enabled"}, {"start": 302.0, "text": "and benefit from these features on all Apple platforms."}, {"start": 306.0, "text": "For those of you building macOS apps, using AppKit's NSTextView,"}, {"start": 310.0, "text": "or the SwiftUI Views discussed, will give you these benefits as well."}, {"start": 315.0, "text": "When the constraints of your app allow, you"}, {"start": 317.0, "text": "should always try to use these components."}, {"start": 321.0, "text": "In my Travel Guide app, I chose to use UITextView's"}, {"start": 325.0, "text": "for each individual paragraph for its accessible properties."}, {"start": 329.0, "text": "The unique layout I designed required me"}, {"start": 331.0, "text": "to use separate text views for each paragraph,"}, {"start": 335.0, "text": "rather than one that contained multiple paragraphs."}, {"start": 338.0, "text": "I'll first assess how I'm doing with my goal"}, {"start": 341.0, "text": "of providing granular text navigation."}, {"start": 344.0, "text": "VoiceOver has a setting that allows someone to choose"}, {"start": 347.0, "text": "what granularity of text is read"}, {"start": 349.0, "text": "when touching their finger on the screen."}, {"start": 352.0, "text": "I have my preference set to lines, so with VoiceOver on,"}, {"start": 355.0, "text": "I am able to tap on any line on the screen"}, {"start": 358.0, "text": "and hear the line read aloud."}, {"start": 360.0, "text": "We started out our morning in Lincoln Park,"}, {"start": 363.0, "text": "strolling through the trails and admiring..."}, {"start": 367.0, "text": "VoiceOver also provides options to change the way it moves,"}, {"start": 371.0, "text": "through a feature called rotors."}, {"start": 373.0, "text": "The active rotor can be changed"}, {"start": 374.0, "text": "using a two finger rotation gesture to switch modes."}, {"start": 378.0, "text": "Now, I will switch into the lines rotor using that gesture,"}, {"start": 382.0, "text": "and swipe down with one finger to find the next line on the page."}, {"start": 388.0, "text": "Lines."}, {"start": 391.0, "text": "...the views of the Chicago skyline."}, {"start": 395.0, "text": "Now, I'll try moving from the end of this paragraph"}, {"start": 398.0, "text": "to the first line of the next one."}, {"start": 403.0, "text": "Right now, because each of these paragraphs are separate views,"}, {"start": 407.0, "text": "VoiceOver is stuck navigating by line within the paragraph,"}, {"start": 411.0, "text": "so someone can't fully explore the page by line"}, {"start": 413.0, "text": "and is why that sound is played."}, {"start": 417.0, "text": "To allow VoiceOver to move between paragraphs seamlessly,"}, {"start": 420.0, "text": "iOS 18 introduced the text navigation APIs."}, {"start": 424.0, "text": "For each text element you want to connect,"}, {"start": 427.0, "text": "return the next and previous accessible text element"}, {"start": 430.0, "text": "that VoiceOver should navigate to."}, {"start": 433.0, "text": "For example, if I have two paragraph views,"}, {"start": 437.0, "text": "I can return Paragraph 2 from Paragraph 1's accessibilityNextTextNavigationElement method,"}, {"start": 443.0, "text": "and Paragraph 1 from Paragraph 2's accessibilityPreviousTextNavigationElement."}, {"start": 450.0, "text": "Here, I have the controller for the pages in my Travel Guide app."}, {"start": 454.0, "text": "During setup, when the configureNavigationElements codepath is run,"}, {"start": 458.0, "text": "I set the the proper navigation element in each direction, where applicable."}, {"start": 464.0, "text": "Now that I've implemented it,"}, {"start": 466.0, "text": "VoiceOver can move past the end of one paragraph"}, {"start": 469.0, "text": "and onto the first line of the next."}, {"start": 472.0, "text": "Before we left the park, we made sure to stop in the free zoo"}, {"start": 476.0, "text": "to check out all of the..."}, {"start": 479.0, "text": "And if you are using SwiftUI, starting in iOS 27,"}, {"start": 484.0, "text": "linking multiple text elements together"}, {"start": 486.0, "text": "using the accessibilityLinkedGroup modifier will achieve the same effect."}, {"start": 491.0, "text": "For example, I have an equivalent page view here"}, {"start": 494.0, "text": "with two selectable text elements."}, {"start": 496.0, "text": "By linking them both with accessibilityLinkedGroup"}, {"start": 499.0, "text": "using the same id and namespace,"}, {"start": 502.0, "text": "they will get the text navigation behavior."}, {"start": 505.0, "text": "And if you are using AppKit on Mac,"}, {"start": 507.0, "text": "check out accessibilitySharedTextUIElements"}, {"start": 510.0, "text": "for a similar result."}, {"start": 513.0, "text": "Now I know that VoiceOver can navigate around the pages of my app"}, {"start": 516.0, "text": "with different text granularities, without any unexpected gaps."}, {"start": 520.0, "text": "But, I also set out to make sure that the continuous reading experience of my app"}, {"start": 525.0, "text": "is as smooth as possible."}, {"start": 528.0, "text": "Paginated content, by nature, requires swiping between pages."}, {"start": 533.0, "text": "The goal is for assistive technologies to interact with this content seamlessly,"}, {"start": 537.0, "text": "without the pages getting in the way."}, {"start": 540.0, "text": "VoiceOver and speak screen both have features"}, {"start": 543.0, "text": "that allow someone to read all content,"}, {"start": 545.0, "text": "from start to end, without having to swipe."}, {"start": 550.0, "text": "I'll explore my current app experience with Speak Screen."}, {"start": 553.0, "text": "To do a read all, I'll swipe down from the top of my screen with two fingers."}, {"start": 559.0, "text": "Midday."}, {"start": 560.0, "text": "At lunchtime, we walked along the Chicago river."}, {"start": 564.0, "text": "The river-front path gave us great views of the city's magnificent architecture."}, {"start": 569.0, "text": "Our favorite view was from the middle of the DuSable Bridge,"}, {"start": 572.0, "text": "where we could look straight down the river."}, {"start": 575.0, "text": "You'll notice that Speak Screen stopped reading"}, {"start": 577.0, "text": "when it got to the bottom of the page."}, {"start": 580.0, "text": "With paginated content, the best experience for a read all"}, {"start": 584.0, "text": "would be to move through all of the pages,"}, {"start": 586.0, "text": "advancing when appropriate, similar to an audiobook."}, {"start": 590.0, "text": "Here I have my apps page view controller again."}, {"start": 593.0, "text": "In my viewDidLoad override,"}, {"start": 595.0, "text": "I can apply the causesPageTurn trait to the last paragraph on my page,"}, {"start": 600.0, "text": "which is available in both UIKit and SwiftUI."}, {"start": 603.0, "text": "And when paired with accessibilityScroll,"}, {"start": 606.0, "text": "Speak Screen and VoiceOver will automatically scroll the page"}, {"start": 610.0, "text": "when it reaches the end."}, {"start": 613.0, "text": "I'll try using Speak Screen with that trait applied to my last paragraph."}, {"start": 619.0, "text": "Midday."}, {"start": 621.0, "text": "At lunchtime, we walked along the Chicago river."}, {"start": 624.0, "text": "The river-front path gave us great views of the city's magnificent architecture."}, {"start": 629.0, "text": "Our favorite view was from the middle of the DuSable Bridge,"}, {"start": 632.0, "text": "where we could look straight down the river."}, {"start": 635.0, "text": "Evening."}, {"start": 636.0, "text": "To end the day, we walked along the lakefront"}, {"start": 639.0, "text": "alongside groups of runners and cyclists."}, {"start": 642.0, "text": "This gave us another great view of the skyline,"}, {"start": 645.0, "text": "towering over the waters of Lake Michigan."}, {"start": 648.0, "text": "Great!"}, {"start": 649.0, "text": "Speak Screen automatically moved focus to the next page when it finished reading,"}, {"start": 654.0, "text": "just like I'd expect."}, {"start": 657.0, "text": "If you recall from earlier,"}, {"start": 659.0, "text": "the last behavior I want to validate is how text selection works with VoiceOver."}, {"start": 664.0, "text": "In my app, I added a feature to save selected content for referencing later"}, {"start": 669.0, "text": "by using a button in the toolbar."}, {"start": 671.0, "text": "I need to make sure this feature is accessible."}, {"start": 676.0, "text": "I'm using a UITextView here, which already has accessible selection."}, {"start": 681.0, "text": "You'll get the same experience by using TextEditor"}, {"start": 684.0, "text": "or text with selection enabled in SwiftUI."}, {"start": 687.0, "text": "But, I also want people to be able"}, {"start": 689.0, "text": "to discover this 'Save recommendation' feature"}, {"start": 692.0, "text": "for their selected text."}, {"start": 694.0, "text": "Visually, I added this button to my toolbar"}, {"start": 697.0, "text": "to save the current selection,"}, {"start": 700.0, "text": "but I can make this even more discoverable to VoiceOver through the edit rotor."}, {"start": 706.0, "text": "To do this, I can create a custom action and add it to VoiceOver's edit rotor"}, {"start": 710.0, "text": "by specifying the edit category when building my action."}, {"start": 714.0, "text": "In my case, I'll override accessibilityCustomActions"}, {"start": 718.0, "text": "on my paragraph UITextView subclass,"}, {"start": 721.0, "text": "and add my Save Recommendation custom action"}, {"start": 724.0, "text": "alongside any actions from the super implementation."}, {"start": 728.0, "text": "Be sure to use the edit category when you have a custom action"}, {"start": 731.0, "text": "that would be associated with text selection,"}, {"start": 734.0, "text": "rather than a generic action."}, {"start": 737.0, "text": "Now, I'm going to turn VoiceOver on to try it out."}, {"start": 741.0, "text": "To select text, I'll switch to the text selection rotor, switch to word edit mode,"}, {"start": 746.0, "text": "and increase my selection by swiping right."}, {"start": 751.0, "text": "Text selection."}, {"start": 752.0, "text": "Swipe right to expand selection."}, {"start": 755.0, "text": "Swipe left to shrink selection."}, {"start": 757.0, "text": "Word selection."}, {"start": 759.0, "text": "\"Our favorite view was from the DuSable Bridge...\" selected."}, {"start": 770.0, "text": "With the text selected, I'll switch to the edit rotor,"}, {"start": 774.0, "text": "and activate the Save Selection action to save it."}, {"start": 778.0, "text": "Lines."}, {"start": 779.0, "text": "Words."}, {"start": 780.0, "text": "Characters."}, {"start": 781.0, "text": "Edit."}, {"start": 783.0, "text": "Save selection."}, {"start": 785.0, "text": "Text saved."}, {"start": 787.0, "text": "Great!"}, {"start": 788.0, "text": "Now I have an accessible app experience using system text views,"}, {"start": 792.0, "text": "and unlocked a new set of accessible reading features by adopting APIs."}, {"start": 797.0, "text": "Line navigation across elements, continuous reading,"}, {"start": 800.0, "text": "and text selection all work as I'd expect."}, {"start": 804.0, "text": "And the best part is that VoiceOver and Speak Screen"}, {"start": 807.0, "text": "aren't the only technologies to benefit from these changes."}, {"start": 811.0, "text": "Since iOS 26, someone can open the Accessibility Reader,"}, {"start": 815.0, "text": "a tool designed to display text content for easier consumption."}, {"start": 819.0, "text": "I have added the reader control to my control center,"}, {"start": 822.0, "text": "so pressing that opens my app's content in the Accessibility Reader."}, {"start": 827.0, "text": "Implementing accessible text practices like I've shared so far"}, {"start": 830.0, "text": "will make the reader experience better for your content as well."}, {"start": 835.0, "text": "That's how you make standard text views accessible for reading content,"}, {"start": 839.0, "text": "and while I'd always recommend reaching for those views first,"}, {"start": 842.0, "text": "not every situation allows for them."}, {"start": 845.0, "text": "Now I'm going to focus on what you should do when you are using custom text,"}, {"start": 849.0, "text": "or custom text elements, in your app to make them accessible."}, {"start": 854.0, "text": "Using custom text is a common pattern seen in dedicated reading apps"}, {"start": 859.0, "text": "to support advanced typography,"}, {"start": 861.0, "text": "share the code across a developer's applications,"}, {"start": 863.0, "text": "or displaying of scanned pages."}, {"start": 866.0, "text": "When I travel, I like to take hand written notes on the places I go,"}, {"start": 871.0, "text": "so I've decided to replace my text views with scanned in pages from my notebook"}, {"start": 875.0, "text": "to give it a more personal touch."}, {"start": 878.0, "text": "Unfortunately, this means that I've lost the accessibility behavior"}, {"start": 882.0, "text": "that UITextView gave me for free,"}, {"start": 884.0, "text": "including the most basic thing: reading out the text."}, {"start": 888.0, "text": "Morning."}, {"start": 889.0, "text": "Heading."}, {"start": 890.0, "text": "Image."}, {"start": 894.0, "text": "The best way to make this content accessible"}, {"start": 897.0, "text": "is by using the UITextInput protocol,"}, {"start": 899.0, "text": "which can be adopted on any accessibility element."}, {"start": 903.0, "text": "This protocol can make rendered text or text in images, for example,"}, {"start": 908.0, "text": "just as accessible as if they were in standard text views."}, {"start": 913.0, "text": "Fully implementing UITextInput gives you the same text experience you'd get"}, {"start": 917.0, "text": "as if you were using a native text view."}, {"start": 920.0, "text": "You'll get line-by-line touch exploration with VoiceOver,"}, {"start": 923.0, "text": "granular navigation with the VoiceOver rotor and Speak Screen,"}, {"start": 927.0, "text": "and text selection."}, {"start": 931.0, "text": "To implement this protocol, you will have to solve for a few problems."}, {"start": 935.0, "text": "You'll need to manage the geometry of your text,"}, {"start": 937.0, "text": "and compute selection rectangles for a given range,"}, {"start": 940.0, "text": "for example in the selectionRects method."}, {"start": 944.0, "text": "When an assistive technology queries for a range in your view,"}, {"start": 947.0, "text": "you'll need to be able to return just that portion of text."}, {"start": 951.0, "text": "And importantly, you'll need to provide a tokenizer,"}, {"start": 954.0, "text": "which will help manage navigation by line, sentence, word, or character."}, {"start": 961.0, "text": "And these are just a few things you'll need to implement."}, {"start": 964.0, "text": "To get all of the accessibility benefits of this protocol,"}, {"start": 967.0, "text": "make sure you implement it in its entirety."}, {"start": 971.0, "text": "In my app, I've implemented this protocol on my accessibility elements"}, {"start": 975.0, "text": "to make the text accessible."}, {"start": 978.0, "text": "Here, I've implemented the selectionRects method from this protocol,"}, {"start": 982.0, "text": "which determines how VoiceOver"}, {"start": 984.0, "text": "and other assistive technology 'highlight' my content."}, {"start": 988.0, "text": "Since I'm working with handwriting from an image,"}, {"start": 990.0, "text": "I can use the known height and width of each line"}, {"start": 993.0, "text": "to compute the approximate rects"}, {"start": 995.0, "text": "for a given range using a custom function, selectionRectFromImage."}, {"start": 1000.0, "text": "I then use this information to build out my array of selection rects,"}, {"start": 1004.0, "text": "which I'll return from this method."}, {"start": 1008.0, "text": "I'll also complete implementations"}, {"start": 1010.0, "text": "for the rest of the methods in the protocol,"}, {"start": 1012.0, "text": "such as grabbing the right substring for textInRange"}, {"start": 1015.0, "text": "and providing a tokenizer."}, {"start": 1017.0, "text": "In my case, I've subclassed the UITextInputStringTokenizer"}, {"start": 1022.0, "text": "provided by UIKit to create a custom tokenizer"}, {"start": 1025.0, "text": "that works with my implementation, so I'll return that."}, {"start": 1029.0, "text": "Lastly, I want my selection experience"}, {"start": 1032.0, "text": "to feel complete visually with selection handles and highlights."}, {"start": 1036.0, "text": "To do this, I added a UITextInteraction to my page view,"}, {"start": 1041.0, "text": "and call the input delegate when my selection changes,"}, {"start": 1044.0, "text": "so the system knows to update the visuals."}, {"start": 1047.0, "text": "This isn't required as part of the UITextInput implementation,"}, {"start": 1050.0, "text": "but rounds out my app by matching expectations"}, {"start": 1053.0, "text": "about the experience in a standard text view."}, {"start": 1057.0, "text": "UITextInput also works great in conjunction with the causesPageTurn"}, {"start": 1061.0, "text": "and navigation element APIs,"}, {"start": 1063.0, "text": "so I've made sure to implement those as well in the new version of my app."}, {"start": 1069.0, "text": "I've finished updating my app,"}, {"start": 1071.0, "text": "taking the time to carefully implement the rest of the UITextInput protocol"}, {"start": 1075.0, "text": "on my scanned in text"}, {"start": 1076.0, "text": "and ensuring that I've implemented all of the APIs necessary."}, {"start": 1080.0, "text": "So, now I am going check out the VoiceOver experience."}, {"start": 1084.0, "text": "First, I'm going to navigate by line."}, {"start": 1088.0, "text": "Lines."}, {"start": 1089.0, "text": "We started out our morning in Lincoln Park,"}, {"start": 1092.0, "text": "admiring the views"}, {"start": 1094.0, "text": "of the Chicago skyline."}, {"start": 1096.0, "text": "The zoo had lots of animals."}, {"start": 1101.0, "text": "Now, I will select some text by switching into the text selection rotor"}, {"start": 1105.0, "text": "and swiping right."}, {"start": 1106.0, "text": "Text selection."}, {"start": 1108.0, "text": "Swipe right to expand selection."}, {"start": 1110.0, "text": "Swipe left to shrink selection."}, {"start": 1113.0, "text": "Line selection."}, {"start": 1115.0, "text": "\"The zoo had lots of animals\" selected."}, {"start": 1118.0, "text": "Lines."}, {"start": 1119.0, "text": "Words."}, {"start": 1120.0, "text": "Characters."}, {"start": 1121.0, "text": "Edit."}, {"start": 1123.0, "text": "Save selection."}, {"start": 1124.0, "text": "Text saved."}, {"start": 1128.0, "text": "And finally, I can try a read-all."}, {"start": 1131.0, "text": "Morning. Heading."}, {"start": 1133.0, "text": "We started out our morning in Lincoln Park,"}, {"start": 1135.0, "text": "admiring the views of the Chicago skyline."}, {"start": 1138.0, "text": "The zoo had lots of animals."}, {"start": 1140.0, "text": "Midday. Heading."}, {"start": 1142.0, "text": "At lunchtime, we walked along the Chicago river."}, {"start": 1145.0, "text": "The view from the DuSable Bridge was perfect for photos!"}, {"start": 1149.0, "text": "Amazing!"}, {"start": 1150.0, "text": "It all works seamlessly."}, {"start": 1153.0, "text": "Now that I've covered what makes a great reading experience,"}, {"start": 1156.0, "text": "and the APIs that make it possible, it's time for you to examine your own app."}, {"start": 1163.0, "text": "Audit your app with VoiceOver on, trying out the read all gesture,"}, {"start": 1167.0, "text": "navigate using the lines rotor, and selecting text."}, {"start": 1171.0, "text": "If you are using standard text views, consider adopting causesPageTurn"}, {"start": 1175.0, "text": "and the text navigation element APIs for a smooth cross-page reading behavior."}, {"start": 1181.0, "text": "If you use custom rendered text, adopt UITextInput."}, {"start": 1186.0, "text": "Doing this work will enable a great experience"}, {"start": 1189.0, "text": "for everyone who downloads your app."}, {"start": 1191.0, "text": "Happy reading!"}]}