PSPDFKit 12.3 Migration Guide
This guide covers updating an iOS or Mac Catalyst project from PSPDFKit 12.2 for iOS to PSPDFKit 12.3 for iOS. We encourage you to update to take advantage of future new features and fixes.
To determine if you need to take action, check the list of the deprecated APIs. If you use a deprecated API in your project, take appropriate action.
New Menu System for Selected Text and Images
PSPDFKit 12.3 for iOS adopts the modern menu system for selected text and images. The modern menu system, previously introduced in PSPDFKit 12 for iOS for annotation creation and selection menus, uses the UIMenu
-based API to display either a horizontal bar or a context menu, depending on platform and input type.
The entire UIMenuItem
-based legacy menu system is now deprecated, and the related APIs will be removed in a future version of PSPDFKit for iOS.
Customizing the Menus Directly
PDFViewController
now offers two new delegate methods for customizing the text and image selection menus directly:
-
pdfViewController(_:
menuForText: onPageView: appearance: suggestedMenu:) -
pdfViewController(_:
menuForImage: onPageView: appearance: suggestedMenu:)
The example below appends a custom action to the menu for selected text:
func pdfViewController(_ sender: PDFViewController, menuForText glyphs: GlyphSequence, onPageView pageView: PDFPageView, appearance: EditMenuAppearance, suggestedMenu: UIMenu) -> UIMenu { let customAction = UIAction(title: "Custom") { _ in print("Hello from custom action!") } return suggestedMenu.replacingChildren(suggestedMenu.children + [customAction]) }
Use UIAction
to insert closure-based actions, UICommand
to insert responder chain actions, and UIMenu
to insert submenus. UIDeferredMenuElement
is also supported.
As a result, the following configuration property, delegate methods, and subclassing hooks that were used to customize the text and image selection menus have been deprecated and will be removed in a future version of PSPDFKit for iOS:
-
PDFConfiguration.allowedMenuActions
-
PDFViewControllerDelegate.pdfViewController(_:
shouldShow: atSuggestedTargetRect: forSelectedText: in: on:) -
PDFViewControllerDelegate.pdfViewController(_:
shouldShow: atSuggestedTargetRect: forSelectedImage: in: on:) -
PDFPageView.textSelectionMenuItemForCreatingAnnotation(withType:)
-
PDFPageView.textSelectionView(_:
updateMenuAnimated:)
Presenting Menus for Selected Text or Images
PSPDFKit 12.3 introduces two new methods to PDFPageView
. These methods are used for selecting text or images and presenting menus at the same time:
As a result, the following methods that were used to present text and image selection menus have been deprecated and will be removed in a future version of PSPDFKit for iOS:
-
PDFViewController.showMenuIfSelected(with:
animated:) -
PDFPageView.showMenuIfSelected(with:
animated:) -
PDFPageView.showMenu(for:
animated:) -
PDFPageView.showMenuIfSelected(animated:)
Backward Compatibility Considerations
The new UIMenu
-based delegate methods are incompatible with the deprecated UIMenuItem
-based delegate methods and PDFPageView
subclassing hooks, and they must not be mixed.
Because the new customizations mark a significant departure from the now-deprecated UIMenuItem
-based API, PSPDFKit 12.3 will ease the transition by choosing to stick with the legacy menu system under certain conditions.
I’m not interested in customizing menus.
If you’re not interested in customizing menus and you don’t use any of the new or deprecated customizations, the modern menu system will be used by default.
I want to customize menus and I want to adopt the modern menu system.
If you implement either of the new UIMenu
-based delegate methods to customize the text or image selection menu, this will be treated as an explicit opt-in to the modern menu system for that specific menu, even if you still have one of the deprecated delegate methods or subclassing hooks in your code.
I’ve been customizing menus but I’m not ready to implement the new UIMenu-based API yet.
If you don’t implement any of the new UIMenu
-based delegate methods but you do have one of the deprecated delegate methods or subclassing hooks in your code, PSPDFKit will stick with the legacy menu system and respect the deprecated customizations.
If this is the case, PSPDFKit will help you identify which exact deprecated customization caused it to opt out of the modern menu system by logging a warning similar to the following:
Presenting the legacy menu for configuration (...) because the following deprecated customizations are implemented: 'MyDelegate.pdfViewController(_:shouldShow:atSuggestedTargetRect:forSelectedText:in:on:)', 'MyPageView.textSelectionMenuItemForCreatingAnnotation(withType:)'. Remove them or implement 'MyDelegate.pdfViewController(_:menuForText:onPageView:appearance:suggestedMenu:)' to explicitly opt into the modern menu system.
This is a temporary mechanism designed to ease the transition to the modern menu system. The legacy menu system is limited and may exhibit problems. The deprecated APIs will eventually be removed, and the legacy menu system will cease to exist. We strongly encourage you to adopt the modern menu system as soon as possible. If you need help, reach out to us on support.
Use Cases
This section explores the most common use cases when customizing the text and image selection menus, and it describes how to achieve the same results using the new UIMenu
-based API.
Presenting Menu for Selected Text or Images
Use the new select(glyphs:
method to select text and set true
for the presentMenu
parameter. It’s no longer possible to present the menu for text without selecting it at the same time:
// Before this update. pageView.selectionView.selectedGlyphs = glyphs pageView.selectionView.updateMenu(animated: true)
// After this update. pageView.select(glyphs: glyphs, presentMenu: true, animated: true)
Presenting the Menu for Selected Images
Use the new select(image:
method to select an image and set true
for the presentMenu
parameter. It’s no longer possible to present the menu for an image without selecting it at the same time:
// Before this update. pageView.selectionView.selectedImage = image pageView.selectionView.updateMenu(animated: true)
// After this update. pageView.select(image: image, presentMenu: true, animated: true)
Customizing the Menu for Selected Text
Use the new pdfViewController(_:
delegate method to customize the menu that appears when you select text:
// Before this update. func pdfViewController(_ pdfController: PDFViewController, shouldShow menuItems: [MenuItem], atSuggestedTargetRect rect: CGRect, forSelectedText selectedText: String, in textRect: CGRect, on pageView: PDFPageView) -> [MenuItem] { // Return the customized `menuItems`. }
// After this update. func pdfViewController(_ sender: PDFViewController, menuForText glyphs: GlyphSequence, onPageView pageView: PDFPageView, appearance: EditMenuAppearance, suggestedMenu: UIMenu) -> UIMenu { // Return the customized `suggestedMenu`. }
To disable the text selection menu, return a UIMenu
with no children from the delegate method above. To disable selecting text entirely, set the isTextSelectionEnabled
configuration property to false
. Note that disabling selecting text will disable selecting images as well.
Customizing the Menu for Selected Images
Use the new pdfViewController(_:
delegate method to customize the menu that appears when you select text:
// Before this update. func pdfViewController(_ pdfController: PDFViewController, shouldShow menuItems: [MenuItem], atSuggestedTargetRect rect: CGRect, forSelectedImage selectedImage: ImageInfo, in imageRect: CGRect, on pageView: PDFPageView) -> [MenuItem] { // Return the customized `menuItems`. }
// After this update. func pdfViewController(_ sender: PDFViewController, menuForImage image: ImageInfo, onPageView pageView: PDFPageView, appearance: EditMenuAppearance, suggestedMenu: UIMenu) -> UIMenu { // Return the customized `suggestedMenu`. }
To disable the image selection menu, return a UIMenu
with no children from the above delegate method. To disable selecting images entirely, set the isImageSelectionEnabled
configuration property to false
. Note that selecting images will be disabled by default if selecting text is also disabled.
Filtering Suggested Menu Elements
Use one of the new UIMenu
-based delegate methods and modify the suggestedMenu
parameter to exclude certain actions or submenus. Keep in mind that you need to search the entire menu tree, and not just the children of the root menu:
// Before this update. func pdfViewController(_ pdfController: PDFViewController, shouldShow menuItems: [MenuItem], atSuggestedTargetRect rect: CGRect, forSelectedText selectedText: String, in textRect: CGRect, on pageView: PDFPageView) -> [MenuItem] { menuItems.filter { $0.identifier == TextMenu.annotationMenuCopy.rawValue || $0.identifier == TextMenu.annotationMenuShare.rawValue } }
// After this update. func pdfViewController(_ sender: PDFViewController, menuForText glyphs: GlyphSequence, onPageView pageView: PDFPageView, appearance: EditMenuAppearance, suggestedMenu: UIMenu) -> UIMenu { suggestedMenu.reject(actions: [.PSPDFKit.copy, .PSPDFKit.share]) }
In the example above, the
reject(actions:)
function isn’t part of the public API, but you can view its source in our Catalog example project.
Inserting Custom Menu Elements
Use one of the new UIMenu
-based delegate methods and modify the suggestedMenu
parameter to insert a menu element at any index:
// Before this update. func pdfViewController(_ pdfController: PDFViewController, shouldShow menuItems: [MenuItem], atSuggestedTargetRect rect: CGRect, forSelectedText selectedText: String, in textRect: CGRect, on pageView: PDFPageView) -> [MenuItem] { let customMenuItem = MenuItem(title: "Custom") { print("Hello from custom menu item!") } return [customMenuItem] + menuItems }
// After this update. func pdfViewController(_ sender: PDFViewController, menuForText glyphs: GlyphSequence, onPageView pageView: PDFPageView, appearance: EditMenuAppearance, suggestedMenu: UIMenu) -> UIMenu { let customAction = UIAction(title: "Custom") { _ in print("Hello from custom action!") } return suggestedMenu.replacingChildren([customAction] + suggestedMenu.children) }
Always Show the Speak Text Menu Action
Before this update, we used to always show the Speak action, which speaks selected text out loud, in the text selection menu. Starting with PSPDFKit 12.3 for iOS, this menu action is now only shown if the Speak Selection accessibility option is enabled in the Settings app.
To restore the behavior of the previous version and always show the Speak and Stop actions for reading content out loud, you can customize the menu in the following way:
// After this update. func pdfViewController(_ sender: PDFViewController, menuForText glyphs: GlyphSequence, onPageView pageView: PDFPageView, appearance: EditMenuAppearance, suggestedMenu: UIMenu) -> UIMenu { let newAccessibilityMenu = UIMenu(identifier: .PSPDFKit.accessibility, options: [.displayInline], children: [stopAction() ?? speakAction(for: glyphs, pageView: pageView)]) return suggestedMenu.replacingChildren(suggestedMenu.children.compactMap { element in if let menu = element as? UIMenu, menu.identifier == .PSPDFKit.accessibility { return newAccessibilityMenu } else { return element } }) } func stopAction() -> UIAction? { let speechSynthesizer = SDK.shared.speechController.speechSynthesizer guard speechSynthesizer.isSpeaking else { return nil } return UIAction(title: "Stop", image: UIImage(systemName: "stop"), attributes: [.keepsMenuPresented]) { _ in speechSynthesizer.stopSpeaking(at: .immediate) } } func speakAction(for glyphs: GlyphSequence, pageView: PDFPageView) -> UIAction { return UIAction(title: "Speak", image: UIImage(systemName: "play"), attributes: [.keepsMenuPresented]) { _ in SDK.shared.speechController.speakText(glyphs.trimmedText, delegate: pageView.selectionView) } }
Further Reading
For more information about the modern menu system, check out our customizing menus on iOS guide and the API documentation for PDFViewControllerDelegate
, GlyphSequence
, PDFPageView
, and ContentMenuConfiguration
.
Check out the PSPDFKit 12 migration guide as well if you’re upgrading from a version older than that. It describes how to adopt the modern menu system for annotation creation and selection menus.
Deprecated APIs
This is the list of all symbols that were deprecated in PSPDFKit 12.3 for iOS. If you use, implement, or override any of the following, take appropriate action.
Miscellaneous
-
PSPDFAnnotationCreateActionDidInsertNotification
Observe the.PSPDFAnnotationsAdded
notification. -
PSPDFAnnotationCreateActionInsertedAnnotationsKey
Observe the.PSPDFAnnotationsAdded
notification.
Legacy Menu System
-
MenuItem
See the New Menu System for Selected Text and Images section for more information. -
PSPDFAllowImagesForMenuItems
Displaying menu elements as images is always supported in the modern menu system. -
PDFConfiguration.allowedMenuActions
See the New Menu System for Selected Text and Images section for more information. -
PDFPageView.textSelectionMenuItemForCreatingAnnotation(withType:)
See the New Menu System for Selected Text and Images section for more information. -
PDFViewController.showMenuIfSelected(with:
animated:)
See the New Menu System for Selected Text and Images section for more information. -
PDFPageView.showMenuIfSelected(with:
animated:)
See the New Menu System for Selected Text and Images section for more information. -
PDFPageView.showMenu(for:
animated:)
See the New Menu System for Selected Text and Images section for more information. -
PDFPageView.showMenuIfSelected(animated:)
See the New Menu System for Selected Text and Images section for more information. -
PDFPageView.textSelectionView(_:
updateMenuAnimated:)
See the New Menu System for Selected Text and Images section for more information. -
TextSelectionView.discardSelection(animated:)
UsePDFPageView.discardSelection(animated:)
to discard any selection on the given page. -
TextSelectionView.updateMenu(animated:)
See the New Menu System for Selected Text and Images section for more information. -
PDFViewControllerDelegate.pdfViewController(_:
shouldShow: atSuggestedTargetRect: forSelectedText: in: on:)
See the New Menu System for Selected Text and Images section for more information. -
PDFViewControllerDelegate.pdfViewController(_:
shouldShow: atSuggestedTargetRect: forSelectedImage: in: on:)
See the New Menu System for Selected Text and Images section for more information. -
FlexibleToolbar.menuItem(for:)
UseUIButton.menu
to add context menus to toolbar buttons. -
FlexibleToolbar.showMenu(with:
target: animated:)
UseUIButton.menu
to add context menus to toolbar buttons. -
FlexibleToolbar.showMenu(forCollapsedButtons:
from: animated:)
UseUIButton.menu
to add context menus to toolbar buttons.
Legacy Menu Item Identifiers
-
TextMenu
UseUIAction.Identifier
orUIMenu.Identifier
in the modern menu system. -
TextMenu.copy
Use the.PSPDFKit.copy
action identifier in the modern menu system. -
TextMenu.createLink
This value is no longer used in the modern menu system. -
TextMenu.define
Use the.PSPDFKit.define
action identifier in the modern menu system. -
TextMenu.pause
Use the.PSPDFKit.accessibility
menu identifier in the modern menu system. -
TextMenu.saveAs
Use the.PSPDFKit.saveAs
action identifier in the modern menu system. -
TextMenu.share
Use the.PSPDFKit.share
action identifier in the modern menu system. -
TextMenu.speak
Use the.PSPDFKit.accessibility
menu identifier in the modern menu system. -
TextMenu.wikipedia
This value is no longer used in the modern menu system. -
TextMenu.annotationMenuHighlight
This value is no longer used in the modern menu system. -
TextMenu.annotationMenuRedaction
This value is no longer used in the modern menu system. -
TextMenu.annotationMenuSquiggle
This value is no longer used in the modern menu system. -
TextMenu.annotationMenuStrikeout
This value is no longer used in the modern menu system. -
TextMenu.annotationMenuUnderline
This value is no longer used in the modern menu system.