Some test text!

Config annotation tools

Customize annotation interactions in iOS viewer

Annotation and PDF interaction is implemented within the open-source Tools.framework . This includes annotation creation & selection, text selection, form filling and link following.

The behavior is implemented via a collection of "Tools": classes that derive from the abstract base class PTTool and that are coordinated by a PTToolManager. The PTToolManager provides the ability to customize tool behavior, and enable/disable the ability for users to create or edit annotations (both in general and on an annotation type by annotation type basis).

Create and edit annotations

To disable (or re-enable) the ability to create or edit annotations, options can be altered as shown below. When disabled, the relevant annotation tool is removed from the annotation toolbar , and from the UIMenuController.

// disables all text annotation types (highlights, underlines, etc.)
toolManager.highlightAnnotationOptions.canCreate = false
toolManager.highlightAnnotationOptions.canEdit = false
toolManager.underlineAnnotationOptions.canCreate = false
toolManager.underlineAnnotationOptions.canEdit = false
toolManager.strikeOutAnnotationOptions.canCreate = false
toolManager.strikeOutAnnotationOptions.canEdit = false
toolManager.squigglyAnnotationOptions.canCreate = false
toolManager.squigglyAnnotationOptions.canEdit = false

Annotation interaction and UIMenuController

Further control over annotation interaction behaviour via the PTToolManagerDelegate protocol.

There are several methods that allow you to be notified of, and if desired modify or prevent, default behavior from occurring. For all methods, if false is returned, then the default behavior will not occur.

  1. -toolManager:shouldSelectAnnotation:onPageNumber:

    This method is called just before an annotation is selected. The annotation object itself is available for the decision making process, and for further action if needed.

  2. -toolManager:shouldShowMenu:forAnnotation:onPageNumber:

    This method is called just before the selection popup menu is shown. The UIMenuController object is passed so that menu items can be added or removed as required.

  3. -toolManager:shouldHandleLinkAnnotation:orLinkInfo:onPageNumber:

    This method is called just before a link is followed. The link is provided so that alternate action can be taken if required.

  4. -toolManager:shouldSwitchToTool:

    This method is called just before a tool is activated. The tool is available for the decision making process.


The sample code uses -toolManager:shouldShowMenu:forAnnotation:onPageNumber: to restrict use of the UIMenuController to copying and defining text found in the PDF. This is done by stopping the UIMenuController from popping up in any case other than selecting text, and by removing options to highlight/underline etc. from the selected text UIMenuController popup.

// PTToolManagerDelegate method implementation.
func toolManager(_ toolManager: PTToolManager, shouldShowMenu menuController: UIMenuController, forAnnotation annotation: PTAnnot, onPageNumber pageNumber: UInt) -> Bool {
    // Only show quick menu for the text select tool.
    if type(of: toolManager.tool) === TextSelectTool.self {
        // Remove the annotation creation menu items.
        menuController.menuItems = removeAnnotationItems(menuController.menuItems!)
        return true;
    } else {
        return false;

func removeAnnotationItems(_ items: [UIMenuItem]) -> [UIMenuItem] {
    let stringsToRemove = ["Highlight", "Underline", "Squiggly", "Strikeout"]
    // Filter out menu items with titles matching specified strings.
    return items.filter({ (menuItem) -> Bool in
        return !stringsToRemove.contains(menuItem.title)
Default Menu OptionsCustomized Menu Options
Default Text MenuCustom Text Menu
Default Rect MenuCustom Rect Menu

Override classes

Tools.framework frequently creates new instances of objects defined within the framework (e.g. a new instance of PTAnnotEditTool is created when a user taps on an annotation). In order to customize certain aspects of the default behavior, it is required to create and use a subclass of the built-in tool. To enable this without requiring source code modification, Tools.framework includes a system to "inject" an externally defined subclass that will be used by the Tools.framework during its normal operation. This is done via the PTOverrides class as follows:

// EGAnnotEditTool is an externally defined class that derives from PTAnnotEditTool
PTOverrides.overrideClass(PTAnnotEditTool.self, withClass: EGAnnotEditTool.self);

Note that in order to be compatible with the external override system, the base class must conform to the PTOverridable protocol.

Customize by modifying the source code

Because Tools.framework is open source, any and all changes are possible by editing the source code directly. The project is found in /Lib/Tools/src.

If you customize the tools source code, you will likely want to use a universal framework (one that contains architectures for both simulators and devices), which is not done automatically by Xcode. The Tools project includes a custom script step that automatically creates a universal framework, located in a folder next to the default build location, with the name {Debug,Release}-universal.

(Building a universal framework also be done manually by first building for device, then simulator, and using the terminal command xcrun -sdk iphoneos lipo -create to merge the binaries (Tools.framework/Tools) into a universal binary.)

Get the answers you need: Support

UPCOMING WEBINAR: Live tech update and run-through. October 21 @ 11am PDT