1. Home
  2. Foxit MobilePDF SDK
  3. Developer Guide for Foxit PDF SDK for iOS

Developer Guide for Foxit PDF SDK for iOS

Introduction to Foxit PDF SDK for iOS

Have you ever worried about the complexity of the PDF specification? Or have you ever felt lost when asked to build a full-featured PDF app within a limited time-frame? If your answer is “Yes”, then congratulations! You have just found the best solution in the industry for rapidly integrating PDF functionality into your apps.

Why Foxit PDF SDK for iOS is your choice

Foxit is an Amazon-invested leading software provider of solutions for reading, editing, creating, organizing, and securing PDF documents. Foxit PDF SDK libraries have been used in many of today’s leading apps, and they are proven, robust, and battle-tested to provide the quality, performance, and features that the industry’s largest apps demand. Foxit PDF SDK for iOS is a new SDK product which is developed for providing quick PDF viewing and manipulation support for mobile platforms. Customers choose it for the following reasons:

  • Easy to integrate
    Developers can seamlessly integrate Foxit PDF SDK for iOS into their own apps with just a few lines of code.
  • Perfectly designed
    Foxit PDF SDK for iOS is designed with a simple, clean, and friendly style, which provides the best user experience.
  • Flexible customization
    Foxit PDF SDK for iOS provides the source code for the user interface which lets the developers have full control of the functionality and appearance of their apps.
  • Robust performance on mobile platforms
    Foxit PDF SDK for iOS provides an OOM (out-of-memory) recovery mechanism to ensure the app has high robust performance when running the app on a mobile device which offers limited memory.
  • Powered by Foxit’s high fidelity rendering PDF engine
    The core technology of Foxit PDF SDK for iOS is based on Foxit’s PDF engine, which is trusted by a large number of the world’s largest and well-known companies. Foxit’s powerful engine makes the app fast on parsing, rendering, and makes document viewing consistent on a variety of devices.
  • Premium World-side Support
    Foxit offers premium support for its developer products because when you are developing mission critical products you need the best support. Foxit has one of the PDF industry’s largest team of support engineers. Updates are released on a regular basis to improve user experience by adding new features and enhancements.

Foxit PDF SDK for iOS

Foxit PDF SDK for iOS is a Rapid Development Kit for mobile platforms which focuses on helping developers easily integrate powerful Foxit PDF technology into their own apps. With Foxit PDF SDK for iOS, even developers with a limited knowledge of PDF can quickly build a professional PDF viewer with just a few lines of code on the iOS platform.

Foxit PDF SDK for iOS consists of three elements as shown in the following picture.

The three elements for Foxit PDF SDK for iOS

  • PDF Core API
    The PDF Core API is the heart of this SDK and is built on Foxit’s powerful underlying technology. It provides the functionality for basic PDF operation features, and is utilized by the PDF View Control 0.and UI Extensions Component, which ensures the apps can achieve high performance and efficiency. The Core API can be used independently for document rendering, analysis, text extraction, text search, form filling, digital signatures, Pressure Sensitive Ink, certificate and password security,
    annotation creation and manipulation and much more.
  • PDF View Control
    The PDF View Control is a utility class that provides the functionality for developers to interact with rendering PDF documents per their requirements. With Foxit’s renowned and widely used PDF rendering technology at its core, the View Control provides fast and high quality rendering, zooming, scrolling and page navigation features. The View Control derives from platform related viewer classes (e.g. UIView on iOS) and allows for extension to accommodate specific user needs.
  • UI Extensions Component
    The UI Extensions Component is an open source library that provides a customizable user interface with built-in support for text selection, markup annotation, outline navigation, reading bookmarks, full-text searching, form filling, text reflow, attachment, digital/handwritten signature, reflow, document editing and password encryption. These features in the UI Extensions Component are implemented using the PDF Core API and PDF View Control. Developers can utilize these ready-to-use UI implementations to build a PDF viewer quickly with the added benefit of complete flexibility and control to customize the UI design as desired.

From version 4.0, Foxit PDF SDK for iOS makes a big change and optimization for the UI Extensions Component. It wraps the basic UI implementations to FSPDFReader class, such as panel controller, toolbar settings, and alter view, etc. Building a full-featured PDF Reader is getting simpler and easier. Furthermore, users can flexibily customize the features they want through a configuration file.

From version 5.0, Foxit PDF SDK for iOS removes the FSPDFReader class, and move the wrapped APIs in FSPDFReader class to UI Extensions Component. In version 5.0, every element in the built-in UI can be configurable. More advanced APIs and more powerful configuration file are provided for developers to further customize the UI elements, such as showing or hiding a specific panel, top/bottom bar, the items in the top bar, and the items in the View setting bar and More Menu view.

Key Features

Foxit PDF SDK for iOS has several main features which help app developers quickly implement the functions that they really need and reduce the development cost.

Features

PDF Document: Open and close files, set and get metadata.

PDF Page: Parse, render, read, and edit PDF pages.

Render: Graphics engine created on a bitmap for platform graphics device.

Reflow: Rearrange page content.

Crop: Crop PDF pages for better reading.

Text Select: Select text in a PDF document.

Text Search: Search text in a PDF document.

Outline: Directly locate and link to point of interest within a document.

Reading Bookmark: Mark progress and interesting passages as users read.

Annotation: Create, edit and remove annotations.

Layers: Add, edit and remove optional content groups.

Attachments: Add, edit and remove document level attachments.

Form: Fill form with JavaScript support, export and import form data by XFDF/FDF/XML file.

Signature: Sign a PDF document, verify a signature, add or delete a signature field. Add and verify third-party digital signature.

Security: Protect PDFs with password or certificate.

Pan and Zoom: Adjust the magnification and position of the view area to match the area in an adjustable rectangle in the Pan & Zoom window’s thumbnail view of the page.

Print: Print PDF document.

Out of Memory: Recover from an OOM condition.

Note: Outline is the technical term used in the PDF specification for what is commonly known as bookmarks in traditional desktop PDF viewers. Reading bookmarks are commonly used on mobile and tablet PDF viewers to mark progress and interesting passages as users read but are not technically outline and are stored at app level rather than within the PDF itself.

Support robust PDF applications with Foxit PDF SDK for iOS

Development of robust PDF applications is challenging on mobile platforms which has limited memory. When memory allocation fails, applications may crash or exit unexpectedly. To deal with this issue, Foxit PDF SDK for iOS provides an out-of-memory (OOM) mechanism to support applications.

OOM is an evolved feature in Foxit PDF SDK for iOS because of its complexity. The key of OOM mechanism is that Foxit PDF SDK for iOS will monitor the usage of memory and take recovery operations automatically once OOM is detected. During the recovery process, Foxit PDF SDK for iOS reloads the document and page automatically and restores the status to the original before OOM. It means the current reading page and location, as well as page view mode (single or continuous page) can be recovered. However, the data generated from editing will be lost.

Foxit PDF SDK for iOS provides the property “shouldRecover” in FSPDFViewCtrl class. By default, the value of “shouldRecover”” is “YES”. If you do not want to enable the auto-recovery when OOM is detected, you can set “shouldRecover” to “false” as follows:

self.pdfViewCtrl = [[FSPDFViewCtrl alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.pdfViewerCtrl.shouldRecover = NO;

At that time, the application will throw an exception, and may crash or exit unexpectedly.

Evaluation

Foxit PDF SDK for iOS allows users to download trial version to evaluate SDK. The trial version has no difference from the standard licensed version except for the free 21-day trial limitation and the trial watermarks in the generated pages. After the evaluation period expires, customers should contact the Foxit sales team and purchase licenses to continue using Foxit PDF SDK for iOS.

License

Developers should purchase licenses to use Foxit PDF SDK for iOS in their solutions. Licenses grant developers permission to release their apps which utilize Foxit PDF SDK for iOS. However, users are prohibited to distribute any documents, sample code, or source code in the released package of Foxit PDF SDK for iOS to any third party without written permission from Foxit Software Incorporated.

About this Guide

Foxit PDF SDK for iOS is currently available on iOS and Android platforms. This guide is intended for the developers who need to integrate Foxit PDF SDK for iOS into their own apps. It aims at introducing the following sections:

  • Introduction to Foxit PDF SDK for iOS: gives an introduction of Foxit PDF SDK for iOS.
  • Getting Started: illustrates the package structure, running demo, and adding PDF SDK into app.
  • Rapidly Building a PDF Reader: describes how to quickly create a full-featured PDF Reader.
  • Customizing the UI Implementation: introduces how to customize the UI implementation.
  • Creating a custom tool: shows how to create a custom tool.
  • Technical Support: provides support information.

Getting Started

It is very easy to setup Foxit PDF SDK for iOS and see it in action! It takes just a few minutes and we will show you how to use it on the iOS platform. The following sections introduce the structure of the installation package, how to run a demo, and how to create your own project in Xcode.

Requirements

  • iOS 9 or higher
  • Xcode 9.0 or newer for Objective-C; Xcode 9.0 or newer for Swift

What’s in the package

Download the “foxit_mobile_pdf_sdk_ios_en.zip” package, and extract it to a new directory like “foxit_mobile_pdf_sdk_ios_en” as shown in Figure 2-1. The package contains:

  • docs: A folder containing API references, developer guide.
  • libs: A folder containing license files, SDK framework, and UI Extensions Component and source code.
  • samples: A folder containing iOS sample projects.
  • getting_started_ios.pdf: A quick guide for Foxit PDF SDK for iOS.
  • legal.txt: Legal and copyright information.
  • release_notes.txt: Release information.

 

Figure 2-1

In the “libs” folder as shown in Figure 2-2, there are items that make up the core components of Foxit PDF SDK for iOS.

Figure 2-2

  • FoxitRDK.framework – The framework that includes the Foxit PDF SDK for iOS dynamic library and associated header files.
  • libFoxitRDKUIExtensions.a – It’s a universal static library (for both simulator and iOS device) generated by the “uiextensions” project found in the “libs/uiextensions_src” folder.
  • uiextensions project- found in the “libs/uiextensions_src” folder. It is an open source library that contains some ready-to-use UI module implementations, which can help developers rapidly embed a fully functional PDF reader into their iOS app. Of course, developers are not forced to use the default UI, they can freely customize and design the UI for their specific apps through the “uiextensions” project.

How to run a demo

Download and install Xcode IDE (https://developer.apple.com/download/).

Note: In this guide, we do not cover the installation of Xcode. You can refer to Apple’s developer site if you haven’t installed it already.

Foxit PDF SDK for iOS provides three useful demos in both Objective-C and Swift programming languages for developers to learn how to call the SDK. The Swift demos are located in the “swift” folder. (See Figure 2-3)

Note: From version 5.1, Foxit PDF SDK for iOS provides a multiple document demo in Swift to show you how to use Foxit SDK to support viewing multiple PDF documents.

Figure 2-3

Function demo

The function demo is provided with Objective-C and Swift programming languages, which is used to show how to use Foxit PDF SDK for iOS to realize some specific features related with PDF. This demo includes the following features:

  • pdf2txt: extract all the text from a PDF document, and then save them to a text file.
  • outline: edit outline (aka bookmark) appearances and titles.
  • annotation: add some annotations to one page of a PDF page.
  • docinfo: export basic information of a PDF to a TXT file.
  • render: render a specified page of a PDF to a Bitmap, and save the bitmap.
  • signature: add a signature to PDF, sign PDF and verify the signature.

To run it in XCode, follow the steps below:

    • Double-click function_demo.xcodeproj found in the “samples/function_demo” folder to open the demo in Xcode. (For Swift, double-click function_demo_swift.xcodeproj found in the “samples/swift/function_demo_swift” folder)Note: There is another way to open the demo in Xocde: double-click samples_xcworkspace found in the “samples” folder. It is a workspace including the three demos.
      Note: There is another way to open the demo in Xcode: double-click samples_xcworkspace found in the “samples” folder. It is a workspace including the three demos.
    • Click on “Product -> Run” to run the demo on an iOS device or simulator. In this guide, an iPhone 7 Simulator will be used as an example. After building the demo successfully, the features are listed like the Figure 2-4.

 

Figure 2-4

    • Click the feature buttons in the above picture to perform the corresponding actions. For example, click “pdf2txt”, and then a message box will be popped up as shown in Figure 2-5. It shows where the text file was saved to. Just run the demo and try the features.

 


Figure 2-5

Viewer control demo

The viewer control demo is provided with Objective-C and Swift programming languages, which is used to demonstrate how to implement the features related to the View Control feature level, such as performing annotations (note, typewriter, highlight, underline, strikeout, squiggly, etc.), outline, reading bookmarks and text search. The logical structure of the code is quite clear and simple so that developers can quickly find the detailed implementation of features which are used widely in PDF apps, such as a PDF viewer. With this demo, developers can take a closer look at the APIs provided in Foxit PDF SDK for iOS.

To run the demo in Xcode, please refer to the setup steps outlined in the Function demo.

Figure 2-8 shows what the demo looks like after it was built successfully. Here, an iPhone 8 Simulator will be used as an example to run the demo.

Figure 2-6

This demo provides the features like text search and listing reading bookmarks, outline and annotations.
For example, click on the button below:

Then, select the second tab (outline). The outline of this document will be displayed as shown in Figure 2-9.

Note: Outline is the technical term used in the PDF specification for what is commonly known as bookmarks in traditional desktop PDF viewers. Reading bookmarks are commonly used on mobile and tablet PDF viewers to mark progress and interesting passages as users read but are not technically outlines and are stored at app level rather than within the PDF itself.

Figure 2-7

Multiple Documents Demo

The Multiple documents demo demonstrates how to use Foxit SDK to support viewing multiple PDF documents.

To run the demo in XCode, please refer to the setup steps outlined in the Function demo.

Figure 2-8 shows what the demo looks like after it was built successfully. Here, an iPhone 8 Simulator will be used as an example to run the demo.

Figure 2-8

Choose and open a PDF file (e.g. “Sample.pdf”). To open another document, click button:

(See Figure 2-9)

After selecting a PDF document (e.g. “complete_pdf_viewer_guide_ios.pdf”), it will be displayed as shown in Figure 2-10. Now, you can browse the two PDF documents by switching the tabs.

Figure 2-9

Figure 2-10

Complete PDF viewer demo

The complete PDF viewer demo demonstrates how to use Foxit PDF SDK for iOS to realize a completely full-featured PDF viewer which is almost ready-to-use as a real world mobile PDF reader. This demo utilizes all of the features and built-in UI implementations which are provided in Foxit PDF SDK for iOS.

To run the demo in Xcode, please refer to the setup steps outlined in the Function demo.

Here, an iPhone 8 Simulator will also be used as an example to run the demo. After building the demo successfully, on the start screen, choose a PDF file (e.g.”complete_pdf_viewer_guide_ios.pdf”), click it and then it will be opened and displayed as shown in Figure 2-11.

Note: If you want to use some other PDF files to test this demo, you need to put them onto the “Document” folder of the device.

Figure 2-11

This demo realizes a completely full-featured PDF viewer, please feel free to run it and try it.

For example, it provides the page thumbnail feature. You can click the View menu, choose the Thumbnail as shown in Figure 2-12, and then the thumbnail of the document will be displayed as shown in Figure 2-13.

Figure 2-12

Figure 2-13

 

Foxit PDF SDK for iOS wrapped all of the UI implementations including the basic UI for app and ready-to- use UI feature modules to UI Extensions Component, so that developers can easily and rapidly build a full-featured PDF Reader with just a few lines of code. This section will help you to quickly get started with using Foxit PDF SDK for iOS to make a full-featured PDF Reader app in Objective-C and Swift with step-by-step instructions provided.

Make an iOS app in Objective-C with Foxit PDF SDK for iOS

This section will help you to quickly make an iOS app in Objective-C using Foxit PDF SDK for iOS. It includes the following steps:

  1. Create a new iOS project in Objective-C
  2. Integrate Foxit PDF SDK for iOS into your apps
  3. Initialize Foxit PDF SDK for iOS
  4. Display a PDF document using PDFViewCtrl
  5. Add UI Extensions Component to build a full-featured PDF Reader

Create a new iOS project in Objective-C

In this guide, we use Xcode 9.1 to create a new iOS project.

Fire up Xcode, choose File -> New -> Project…, and then select iOS -> Single View Application as shown in Figure 3-1. Click Next.

Figure 3-1

Choose the options for your new project as shown in Figure 3-2. Please make sure to choose Objective-C as the programming language. For simplicity, we don’t check the Unit Tests and UI Tests which are used for automated testing. Then, Click Next.

Figure 3-2

Place the project to the location as desired. The option “version control” is not actually important for building your first PDF app, so let’s use the default setting. Here, we place the project to the desktop as shown in Figure 2-13. Then, click Create.

Figure 3-3

Integrate Foxit PDF SDK for iOS into your apps

Note: In this section, we will use the default built-in UI implementations to develop the app, for simplicity and convenience (use the UI Extensions Component directly, and don’t need to build the source code project), we need to add the following files to the pdfreader project.

  • FoxitRDK.framework – The framework that includes the Foxit PDF SDK for iOS dynamic library and associated header files.
  • libFoxitRDKUIExtensions.a – It’s a universal static library (for both simulator and iOS device)generated by the “uiextensions” project found in the “libs/uiextensions_src” folder.
    Note: please keep in mind that you should include the corresponding header files for the classes you need to use in libFoxitRDKUIExtensions.a. Just find them in the “libs/uiextensions_src/uiextensions” folder.
  • Resource files – found in the “libs/uiextensions_src/uiextensions/resource” folder. They are needed for the default built-in UI implementations, such as images, strings and other resources.

Note: The UI Extensions Component (libFoxitRDKUIExtensions.a) and resource files are not required for the section Display a PDF document using PDFViewCtrl, so we just add “FoxitRDK.framework” to the pdfreader project first. In the section Add UI Extensions Component to build a full-featured PDF Reader, we will introduce how to add the UI Extensions Component and resource files.

Add dynamic framework “FoxitRDK.framework”

To add the dynamic framework “FoxitRDK.framework” into the pdfreader project, please follows the steps below:

a) Right-click the “pdfreader” project, select Add Files to “pdfreader”… as shown in Figure 3-4.

Figure 3-4

b) Find and choose “FoxitRDK.framework” in the “libs” folder of the download package, and then click Add as shown in Figure 2-15.

Note: Make sure to check the “Copy items if needed” option.

Figure 3-5

Then, the pdfreader project will look like the Figure 3-6.

Figure 3-6

c) Add the dynamic framework “FoxitRDK.framework” to the Xcode’s Embedded Binaries. Left- click the project, find Embedded Binaries in the General tab, and press on the + button as shown in Figure 3-7.

Figure 3-7

Then, choose the “FoxitRDK.framework” to add, and the Embedded Binaries will be like the Figure 3-8.

Figure 3-8

Now, we have added “FoxitRDK.framework” to the pdfreader project successfully.

Initialize Foxit PDF SDK for iOS

It is necessary for apps to initialize and unlock Foxit PDF SDK for iOS using a license before calling any APIs. The function [FSLibrary init:sn key:key] is provided to initialize Foxit PDF SDK for iOS. The trial license files can be found in the “libs” folder of the download package. After the evaluation period expires, you should purchase an official license to continue using it. Finish the initialization in the didFinishLaunchingWithOptions method within the AppDelegate.m file.

#import "AppDelegate.h"
#import "FoxitRDK/FSPDFObjC.h"
 
@interface AppDelegate ()
 
@end
 
@implementation AppDelegate
 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 
    // The value of "sn" can be found in the "rdk_sn.txt".
    // The value of "key" can be found in the "rdk_key.txt".
    NSString* sn = @" ";
    NSString* key = @" ";
 
  FS_ERRORCODE eRet = [FSLibrary init:sn key:key];
    if (e_errSuccess != eRet) {
        return NO;
    }
    return YES;
}
 
@end

Note: The parameter “sn” can be found in the “rdk_sn.txt” (the string after “SN=”) and the “key” can be found in the “rdk_key.txt” (the string after “Sign=”).

Display a PDF document using PDFViewCtrl

So far, we have added “FoxitRDK.framework” to the pdfreader project, and finished the initialization of the Foxit PDF SDK for iOS. Now, let’s start building a simple PDF viewer with just a few lines of code

Note: The UI Extensions Component is not required if you only want to display a PDF document.

First of all, add a PDF file to the project which will be used as the test file. For example, we use “Sample.pdf” found in the “samples/test_files” folder of the download package. Right-click the pdfreader project, and select Add Files to “pdfreader”… to add this file. After adding, you can see the PDF in the Xcode’s Copy Bundle Resources as shown in Figure 3-9.

Note: You can add the PDF to Copy Bundle Resources directly. Just left-click the pdfreader project, find Copy Bundle Resources in the Build Phases tab, press on the + button, and choose the file to add. You can refer to any PDF file, just add it to the Xcode’s Copy Bundle Resources.

Figure 3-9

Then, add the following code to ViewController.m to display a PDF document. It’s really easy to present a PDF on screen. All you need is to get a PDF file and call [FSPDFViewCtrl openDoc:filePath password:password completion:completion] function to open and display the PDF.

Update ViewController.m as follows:

#import "ViewController.h"
#import "FoxitRDK/FSPDFViewControl.h"
 
@interface ViewController ()
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
     // Get the path of a PDF
     NSString* pdfPath = [[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"pdf"];
 
     // Initialize a PDFDoc object with the path to the PDF file
     FSPDFDoc* pdfdoc = [FSPDFDoc createFromFilePath:pdfPath];
     if(e_errSuccess != [pdfdoc load:nil]) {
         return;
     }
 
    // Initialize a FSPDFViewCtrl object with the size of the entire screen
    FSPDFViewCtrl* pdfViewCtrl;
    pdfViewCtrl = [[FSPDFViewCtrl alloc] initWithFrame: [self.view bounds]];
 
    // Set the document to display
    [pdfViewCtrl setDoc:pdfdoc];
 
    // Add the pdfViewCtrl to the root view
    [self.view addSubview:pdfViewCtrl];
 
}
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
 
@end

Fantastic! We have now finished building a simple iOS app which uses Foxit PDF SDK for iOS to display a PDF document with just a few lines of code. The next step is to run the project on a device or simulator.

In this guide, we build and run the project on an iPhone 8 Simulator, and you will see that the “Sample.pdf” document is displayed as shown in Figure 3-10. Now, this sample app has some basic PDF features, such as zooming in/out and page turning. Just have a try!

Figure 3-10

Add UI Extensions Component to build a full-featured PDF Reader

Foxit PDF SDK for iOS comes with built-in UI design including the basic UI for app and the feature modules UI, which are implemented using Foxit PDF SDK for iOS and are shipped in the UI Extensions Component. Hence, building a full-featured PDF Reader is getting simpler and easier. All you need to do is to add UI Extensions Component, and then instantiate a UIExtensionsManager object and set it to PDFViewCtrl.

Add UI Extensions Component

Note: For simplicity and convenience, we add libFoxitRDKUIExtensions.a to the project directly.

To add libFoxitRDKUIExtensions.a to the project, please follow the steps below:

Step 1: Right-click the pdfreader project, and select Add Files to “pdfreader”… to add the extensions library. After adding, you can see the library in the Xcode’s Link Binary With Libraries as shown in Figure 3-11.

Note: You can add the library to Link Binary With Libraries directly. Just left-click the pdfreader project, find Link Binary With Libraries in the Build Phases tab, press on the + button, and choose the file to add. In either case, please check the “Copy items if needed” option when choosing the file.

Figure 3-11

Step 2: Add “-force_load libFoxitRDKUIExtensions.a -lstdc++” to Other Linker Flags in the Build Settings tab as shown in Figure 3-12. “-force_load libFoxitRDKUIExtensions.a” is used to load all of the members that implement any Objective-C class or category in the static library. “-lstdc++” ensures that the C++ standard library that is required by Foxit PDF SDK for iOS will be included at link time.

Figure 3-12

Step 3: Copy the uiextensions folder from the “libs/uiextensions_src” of the download package to “pdfreader”. This file contains the header files for libFoxitRDKUIExtensions.a. Then, the “pdfreader” folder will look like Figure 3-13.

Note: This project only needs the “UIExtensionsManager.h” file. So you can just add this header file found in the “libs/uiextensions_src/uiextensions” of the download package to the project.

Figure 3-13

Step 4: Add the Resource files that are needed for the built-in UI implementations to the test_objc project. (Note: The Resource files might not be used for form filling feature, but required for the following sections.)

Right-click the pdfreader project, and select Add Files to “pdfreader”… to add the Resource files. Find and choose the folder as shown in Figure 3-14.

Note: If you didn’t copy the uiextensions file to “pdfreader”, please find and choose the file in the “libs/uiextensions_src/uiextensions” of the download package.

Figure 3-14

After completing the above four steps, the pdfreader project will look like Figure 3-15.

Figure 3-15

Add code to instantiate a UIExtensionsManager object and set it to PDFViewCtrl

In the “ViewController.m” file, you only need to add the following code:

#import "../uiextensions/UIExtensionsManager.h"
 
UIExtensionsManager* extensionsManager;
...
extensionsManager = [[UIExtensionsManager alloc] initWithPDFViewControl:pdfViewCtrl];
pdfViewCtrl.extensionsManager = extensionsManager;

The whole update of ViewController.m is as follows:

#import "ViewController.h"
#import "FoxitRDK/FSPDFViewControl.h"
#import "../uiextensions/UIExtensionsManager.h"
 
@interface ViewController ()
 
 
@end
 
@implementation ViewController
{
    UIExtensionsManager* extensionsManager;
}
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    // Get the path of a PDF
    NSString* pdfPath = [[NSBundle mainBundle] pathForResource:@"FoxitForm" ofType:@"pdf"];
 
    // Initialize a PDFDoc object with the path to the PDF file
    FSPDFDoc* pdfdoc = [FSPDFDoc createFromFilePath:pdfPath];
    if(e_errSuccess != [pdfdoc load:nil]) {
        return;
    }
 
    // Initialize a FSPDFViewCtrl object with the size of the entire screen
    FSPDFViewCtrl* pdfViewCtrl;
    pdfViewCtrl = [[FSPDFViewCtrl alloc] initWithFrame: [self.view bounds]];
 
    // Set the document to display
    [pdfViewCtrl setDoc:pdfdoc];
 
    // Add the pdfViewCtrl to the root view
    [self.view addSubview:pdfViewCtrl];
 
 
    // Initialize a UIExtensionsManager object and set it to pdfViewCtrl
    extensionsManager = [[UIExtensionsManager alloc] initWithPDFViewControl:pdfViewCtrl];
    pdfViewCtrl.extensionsManager = extensionsManager;
}
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
 
}
 
@end

Now let’s run it on an iPhone 8 Simulator. Now, it is a full-featured PDF Reader as shown in Figure 3-16, which includes all of the features in Complete PDF Viewer Demo. Feel free to try it.

Figure 3-16

Note:Note: From version 5.0, PDFViewCtrl is a full-screen view, so that you might find that the top toolbar is too close to the system’s status bar (See Figure 3-17), which affects the interface appearance. There are some ways to deal with this problem, such as hiding the status bar, or adjusting the position of the top toolbar. In this guide, we provide a solution as follows, which adjusts the top toolbar’s position in setTopToolBarHidden function

Figure 3-17

#import "ViewController.h"
#import "FoxitRDK/FSPDFViewControl.h"
#import "../uiextensions/UIExtensionsManager.h"
 
@interface ViewController () 
 
@end
 
@implementation ViewController
{
    UIExtensionsManager* extensionsManager;
}
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    // Get the path of a PDF.
    NSString* pdfPath = [[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"pdf"];
 
    // Initialize a FSPDFViewCtrl object with the size of the entire screen.
    FSPDFViewCtrl* pdfViewCtrl;
    pdfViewCtrl = [[FSPDFViewCtrl alloc] initWithFrame: [self.view bounds]];
 
    // Open an unencrypted PDF document.
    [pdfViewCtrl openDoc:pdfPath password:nil completion:nil];
 
    // Add the pdfViewCtrl to the root view.
    [self.view addSubview:pdfViewCtrl];
 
    // Initialize a UIExtensionsManager object and set it to pdfViewCtrl.
    extensionsManager = [[UIExtensionsManager alloc] initWithPDFViewControl:pdfViewCtrl];pdfViewCtrl.extensionsManager = extensionsManager;
    extensionsManager.delegate = self;
}
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
 
#pragma mark 
- (void)uiextensionsManager:(UIExtensionsManager *)uiextensionsManagersetTopToolBarHidden:(BOOL)hidden {
    [UIView animateWithDuration:0.3 animations:^{
        if (hidden) {
            // Hide the top toolbar.
            CGRect frame = uiextensionsManager.topToolbar.frame;
            frame.origin.y = -frame.size.height;
            uiextensionsManager.topToolbar.frame = frame;
        } else {
            CGRect frame = uiextensionsManager.topToolbar.frame;
            frame.origin.y = self.view.safeAreaInsets.top; // for iOS 11 or later.
            uiextensionsManager.topToolbar.frame = frame;
       }
   }];
}
@end

Tip: If you use iOS SDK between 7 and 10, you should use “frame.origin.y = self.topLayoutGuide.length;” to replace “frame.origin.y = self.view.safeAreaInsets.top;

Make an iOS app in Swift with Foxit PDF SDK for iOS

Nowadays, Swift is more and more popular for iOS developers because its syntax is much cleaner and easier to read. To better support Swift developers, this section will help you to quickly get started with using Foxit PDF SDK for iOS to make an iOS app in Swift with step-by-step instructions provided. From now, you can get familiar with Foxit PDF SDK for iOS and use Swift to create your first PDF iOS app in Xcode. This section includes the following steps:

  1. Create a new iOS project in Swift
  2. Integrate Foxit PDF SDK for iOS into your apps
  3. Initialize Foxit PDF SDK for iOS
  4. Apply the license key
  5. Display a PDF document using PDFViewCtrl
  6. Add UI Extensions Component to build a full-featured PDF Reader

Create a new iOS project in Swift

In this guide, we use Xcode 9.1 to create a new iOS project.

To create a new iOS project in Swift, you can refer to section 3.1.1 Create a new iOS project in Objective-C”. The only difference is that you should choose Swift as the programming language (See Figure 3-18).

Integrate Foxit PDF SDK for iOS into your apps (Swift)

 

To integrate Foxit PDF SDK for iOS into your apps, please first refer to the previous “Integrate Foxit PDF SDK for iOS into your apps” section to add the dynamic framework “FoxitRDK.framework” into the test_swift project. Then, create a Swift bridging header which is used for building a bridge between Swift and Objective-C. That means it allows you to communicate with the Objective-C classes from your Swift classes. To create and configure Swift bridging header, please follow the steps blew:

a) In pdfreader project, choose File -> New ->; File…, and then select iOS -> Header File as shown in Figure 3-19. Click Next.

Figure 3-19

b) Name the header file. Example: in this project, the file is named “Bridging-Header” as shown in Figure 3-20. Click Create. Then the pdfreader project will look like the Figure 3-21.

Figure 3-20

Figure 3-21

c) Left-click the pdfreader project, navigate to the Build Settings tab, find the Swift Compiler –General section. You may find it faster to type in “Swift Compiler” into the search box to narrow down the results.

Next to Objective-C Bridging Header, add the created Swift bridging header “Bridging-Header.h”as shown in Figure 3-22.

Figure 3-22

d) Open the “Bridging-Header.h” file, import the Objective-C classes you want to call using #import statements. Any class listed in this file will be able to be accessed from your Swift classes. Now, we import the following two classes first which are required for the section “Display a PDF document using PDFViewCtrl. (See Figure 3-23)

Figure 3-23

Now, we have created and configured a Swift bridging header in the pdfreader project successfully.

Initialize Foxit PDF SDK for iOS

It is necessary for apps to initialize and unlock Foxit PDF SDK for iOS using a license before calling any APIs. The function FSLibrary init:(sn key:key) is provided to initialize Foxit PDF SDK for iOS. The trial license files can be found in the “libs” folder of the download package. After the evaluation period expires, you should purchase an official license to continue using it. Finish the initialization in the application method within the AppDelegate.swift file.

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
 
        let sn = ""
        let key = ""
        let eRet = FSLibrary.init(sn, key:key)
        if FS_ERRORCODE.e_errSuccess != eRet {
            return false
        }
        return true
}
}

Note: The parameter “sn” can be found in the “rdk_sn.txt” (the string after “SN=”) and the “key” can be found in the “rdk_key.txt” (the string after “Sign=”).

Display a PDF document using PDFViewCtrl

So far, we have added “FoxitRDK.framework” to the pdfreader project, and finished the initialization of the Foxit PDF SDK for iOS. Now, let’s start displaying a PDF document with just a few lines of code.

Note: The UI Extensions Component is not required if you only want to display a PDF document.

First of all, add a PDF file to the project which will be used as the test file. For example, we use “Sample.pdf” found in the “samples\test_files” folder of the download package. Right-click the pdfreader project, and select Add Files to “pdfreader“… to add this file. After adding, you can see the PDF in the Xcode’s Copy Bundle Resources as shown in Figure 3-24.

Note: You can add the PDF to Copy Bundle Resources directly. Just left-click the pdfreader project, find Copy Bundle Resources in the Build Phases tab, press on the + button, and choose the file to add. You can refer to any PDF file, just add it to the Xcode’s Copy Bundle Resources.

Figure 3-24

Then, add the following code to ViewController.m to display a PDF document. It’s really easy to present a PDF on screen. All you need is to get a PDF file and call [FSPDFViewCtrl openDoc:filePath password:password completion:completion] function to open and display the PDF.

Update ViewController.swift as follows:

import UIKit
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        // Get the path of a PDF.
        let pdfPath = Bundle.main.path(forResource: "Sample", ofType: "pdf")!
 
        // Initialize a PDFDoc object with the path to the PDF file.
        let doc = FSPDFDoc.create(fromFilePath:pdfPath)
        if e_errSuccess != doc?.load(nil) {
            return
        }
 
        // Initialize a FSPDFViewCtrl object with the size of the entire screen.
        var pdfViewCtrl: FSPDFViewCtrl!
        pdfViewCtrl = FSPDFViewCtrl(frame:self.view.bounds)
 
        // Set the document to display.
        pdfViewCtrl.setDoc(doc)
 
        // Add the pdfViewCtrl to the root view.
        self.view.insertSubview(pdfViewCtrl, at: 0)
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Fantastic! We have now finished building a simple iOS app in Swift which uses Foxit PDF SDK for iOS to display a PDF document with just a few lines of code. The next step is to run the project on a device or simulator.

In this guide, we build and run the project on an iPhone 8 Simulator, and you will see that the “Sample.pdf” document is displayed as shown in Figure 3-25. Now, this sample app has some basic PDF features, such as zooming in/out and page turning. Just have a try!

Figure 3-25

Add UI Extensions Component to build a full-featured PDF Reader

Foxit PDF SDK for iOS comes with built-in UI design including the basic UI for app and the feature modules UI, which are implemented using Foxit PDF SDK for iOS and are shipped in the UI Extensions Component. Hence, building a full-featured PDF Reader is getting simpler and easier. All you need to do is to add UI Extensions Component, and then instantiate a UIExtensionsManager object and set it to PDFViewCtrl.

Add UI Extensions Component

Note: For simplicity and convenience, we add libFoxitRDKUIExtensions.a to the project directly.

To add libFoxitRDKUIExtensions.a to the project, please follow the steps below:

Step 1: Right-click the pdfreader project, and select Add Files to “pdfreader”… to add the extensions library. After adding, you can see the library in the Xcode’s Link Binary With Libraries as shown in Figure 3-26.

Note: You can add the library to Link Binary With Libraries directly. Just left-click the pdfreader project, find Link Binary With Libraries in the Build Phases tab, press on the + button, and choose the file to add. In either case, please check the “Copy items if needed” option when choosing the file.

Figure 3-26

Step 2: Add “-force_load libFoxitRDKUIExtensions.a -lstdc++” to Other Linker Flags in the Build Settings tab as shown in Figure 3-27. “-force_load libFoxitRDKUIExtensions.a” is used to load all of the members that implement any Objective-C class or category in the static library. “-lstdc++” ensures that the C++ standard library that is required by Foxit PDF SDK for iOS will be included at link time.

Figure 3-27

Step 3: Copy the uiextensions folder from the “libs/uiextensions_src” of the download package to “pdfreader”. This file contains the header files for libFoxitRDKUIExtensions.a. Then, the “pdfreader” folder will look like Figure 3-28.

Note: This project only needs the “UIExtensionsManager.h” file. So you can just add this header file found in the “libs/uiextensions_src/uiextensions” of the download package to the project.

Figure 3-28

Step 4: Add the Resource files that are needed for the built-in UI implementations to the pdfreader project.

Right-click the pdfreader project, and select Add Files to “test_swift”… to add the Resource files. Find and choose the folder as shown in Figure 3-29.

Note: If you didn’t copy the uiextensions file to pdfreader”, please find and choose the file in the “libs/uiextensions_src/uiextensions” of the download package.

Figure 3-29/strong>

After completing the above four steps, the pdfreader project will look like Figure 3-30.

Figure 3-30

Add code to instantiate a UIExtensionsManager object and set it to PDFViewCtrl

First, open the “Bridging-Header.h” file, import the following header file. (See Figure 3-31)

Then, in the “ViewController.swift” file, you only need to add the following code:

var extensionsManager: UIExtensionsManager !
...
extensionsManager = UIExtensionsManager(pdfViewControl: pdfViewCtrl)
pdfViewCtrl.extensionsManager = extensionsManager;

The whole update of “ViewController.swift” is as follows:

#import "uiextensions/UIExtensionsManager.h"

Figure 3-31

Then, in the “ViewController.swift” file, you only need to add the following code:

var extensionsManager: UIExtensionsManager !
...
extensionsManager = UIExtensionsManager(pdfViewControl: pdfViewCtrl)
pdfViewCtrl.extensionsManager = extensionsManager;

The whole update of “ViewController.swift” is as follows:

import UIKit
 
class ViewController: UIViewController {
 
    var extensionsManager: UIExtensionsManager!
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        // Get the path of a PDF.
        let pdfPath = Bundle.main.path(forResource: "FoxitForm", ofType: "pdf")!
 
        // Initialize a PDFDoc object with the path to the PDF file.
        let doc = FSPDFDoc.create(fromFilePath:pdfPath)
        if e_errSuccess != doc?.load(nil) {
            return
        }
 
        // Initialize a FSPDFViewCtrl object with the size of the entire screen.
        var pdfViewCtrl: FSPDFViewCtrl!
        pdfViewCtrl = FSPDFViewCtrl(frame:self.view.bounds)
 
        // Set the document to display.
        pdfViewCtrl.setDoc(doc)
 
        // Add the pdfViewCtrl to the root view.
        self.view.insertSubview(pdfViewCtrl, at: 0)
 
        // Initialize a UIExtensionsManager object and set it to pdfViewCtrl.
        extensionsManager = UIExtensionsManager(pdfViewControl: pdfViewCtrl)
        pdfViewCtrl.extensionsManager = extensionsManager;
   }     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Let’s run it on an iPhone 8 Simulator. Now, it is a full-featured PDF Reader as shown in Figure 3-32, which includes all of the features in Complete PDF Viewer demo. Feel free to try it.

Figure 3-32

Note: From version 5.0, PDFViewCtrl is a full-screen view, so that you might find that the top toolbar is too close to the system’s status bar (See Figure 3-33), which affects the interface appearance. There are some ways to deal with this problem, such as hiding the status bar, or adjusting the position of the top toolbar. In this guide, we provide a solution as follows, which adjusts the top toolbar’s position in setTopToolBarHidden function.

Figure 3-33

import UIKit
 
class ViewController: UIViewController {
 
    var extensionsManager: UIExtensionsManager!
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        // Get the path of a PDF.
        let pdfPath = Bundle.main.path(forResource: "FoxitForm", ofType: "pdf")!
 
        // Initialize a PDFDoc object with the path to the PDF file.
        let doc = FSPDFDoc.create(fromFilePath:pdfPath)
        if e_errSuccess != doc?.load(nil) {
            return
        }
 
        // Initialize a FSPDFViewCtrl object with the size of the entire screen.
        var pdfViewCtrl: FSPDFViewCtrl!
        pdfViewCtrl = FSPDFViewCtrl(frame:self.view.bounds)
 
        // Set the document to display.
        pdfViewCtrl.setDoc(doc)
 
        // Add the pdfViewCtrl to the root view.
        self.view.insertSubview(pdfViewCtrl, at: 0)
 
        // Initialize a UIExtensionsManager object and set it to pdfViewCtrl.
        extensionsManager = UIExtensionsManager(pdfViewControl: pdfViewCtrl)
        pdfViewCtrl.extensionsManager = extensionsManager;
   }
 
   // MARK: 
   func uiextensionsManager(_ uiextensionsManager: UIExtensionsManager, setTopToolBarHidden
hidden: Bool) {
        UIView.animate(withDuration: 0.3, animations: {() -> Void in
            if hidden {
                // Hide the top toolbar.
                var frame: CGRect = uiextensionsManager.topToolbar!.frame
                frame.origin.y = -frame.size.height
                uiextensionsManager.topToolbar!.frame = frame
           }
           else {
                var frame: CGRect = uiextensionsManager.topToolbar!.frame
                frame.origin.y = self.view.safeAreaInsets.top // for iOS 11 or later
                uiextensionsManager.topToolbar!.frame = frame
          }
       })
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Tip: If you use iOS SDK between 7 and 10, you should use “frame.origin.y = self.topLayoutGuide.length;” to replace “frame.origin.y = self.view.safeAreaInsets.top;

Customizing User Interface

Foxit PDF SDK for iOS provides a simple, clean and friendly user interface for developers to quickly build a full-featured PDF app without needing to take much time on the design. Furthermore, customizing the user interface is straightforward. Foxit PDF SDK for iOS provides the source code of the UI Extensions Component that contains ready-to-use UI module implementations, which lets the developers have full control of styling the appearance as desired.

From version 4.0, developers can flexibly customize the features they want through a configuration file.

From version 5.0, every element in the built-in UI can be configurable. More advanced APIs and more powerful configuration file are provided for developers to further customize the UI elements, such as showing or hiding a specific panel, top/bottom bar, the items in the top bar, and the items in the View setting bar and More Menu view.

The following section will introduce how to customize the feature modules in your project and how to customize the UI elements and implementations through a configuration file or APIs.

About configuration file

From version 4.0, Foxit PDF SDK for iOS provides a more convenient way to flexibly control and customize the features through a configuration file. Developers can easily choose the features that they want without needing to write any additional code or redesign the app’s UI.

Two formats of the configuration file

The configuration file can be provided as a JSON file or implemented directly in code. It controls which feature modules are enabled. Now, we will introduce the two formats of the configuration file respectively.

The first format, use a JSON file (e.g name “uiextensions_config.json”) which should look like as follows:

{
 
    "modules": {
 
        "thumbnail": true,
 
        "readingBookmark": true,
 
        "outline": true,
 
        "tools": true,
 
        "attachment": true,
 
        "signature": true,
 
        "search": true,
 
        "pageNavigation": true,
 
        "form": true,
 
        "encryption": true
 
    }
 
}

Note: For a full-featured PDF Reader, all of the items in “modules” should be set to “true”, which ensures that all of the features are enabled.

Then, use the following code to get the configuration file:

Objective-C:

NSString* configPath = [[NSBundle mainBundle] pathForResource:@"uiextensions_config" ofType:@"json"];

Swfit:

let configPath = Bundle.main.path(forResource: "uiextensions_config", ofType: "json")
var data: Data?
if nil != configPath {
    data = NSData(contentsOfFile: configPath!) as Data?
}

The second format, implement it in the code instead of a JSON file as follows:

Objective-C:

NSDictionary* configContent =
             @{@"modules":@{@"readingbookmark": @true,
                            @"outline": @true,
                            @"annotations": @true,
                            @"thumbnail": @true,
                            @"attachment": @true,
                            @"signature": @true,
                            @"search": @true,
                            @"pageNavigation": @false,
                            @"form": @true,
                            @"selection": @true,
                            @"encryption": @true}
                  };
NSData* configData = [NSJSONSerialization dataWithJSONObject:configContent options:NSJSONWritingPrettyPrinted error: nil];

Swift:

let configContent: String = "{\"modules\": {\n"
                               + "\"readingbookmark\": true,\n"
                               + "\"outline\": true,\n"
                               + "\"annotations\": true,\n"
                               + "\"thumbnail\" : true,\n"
                               + "\"attachment\": true,\n"
                               + "\"signature\": true,\n"
                               + "\"search\": true,\n"
                               + "\"pageNavigation\": false,\n"
                               + "\"form\": true,\n"
                               + "\"selection\": true,\n"
                               + "\"encryption\" : true}}"
let configData: Data? = configContent.data(using: String.Encoding.utf8)

In this guide, we will use the first format (JSON file) to present the configuraton file.

Notice items of configuration file

The JSON configuration file can be written by yourself. There are some situations needed to notice you are writing the configuration file. Following lists some typical examples:

  • All of the items in “modules” are set to “true”, in this case, all of the feature modules will be enabled.
{
    "modules": {
        "thumbnail": true,
        "readingBookmark": true,
        "outline": true,
        "tools": true,
        "annotations": true,
        "attachment": true,
        "signature": true,
        "search": true,
        "pageNavigation": true,
        "form": true,
        "encryption": true
    }
}
  • Some items in “modules” are set to “false”. For example, “search” and “thumbnail” modules are set to “false”, in this case, only the “search” and “thumbnail” feature modules are disabled, the others are all enabled.
{
    "modules": {
        "thumbnail": false,
        "readingBookmark": true,
        "outline": true,
        "tools": true,
        "attachment": true,
        "signature": true,
        "search": false,
        "pageNavigation": true,
        "form": true,
        "selection": true,
        "encryption": true
    }
}
  • Some items in “modules” are not set. For example, “search” and “thumbnail” modules are not set in the configuration file, in this case, the “search” and “thumbnail” feature modules are enabled, because the default settings are “true”. It means if some features modules are not in the configuration file, they will also be available.
{
    "modules": {
        "readingBookmark": true,
        "outline": true,
        "tools": true,
        "attachment": true,
        "signature": true,
        "pageNavigation": true,
        "form": true,
        "encryption": true
    }
}
}

Note:The “tools” item includes the Selection tool and the Annotation tools (except Attachment tool) in the built-in Annotation setting bar.

From version 5.0, Foxit PDF SDK for iOS supports customizing the annotations in the built-in Annotation setting bar through a configuration file, so that developers can choose the annotations that they want without needing to write any additional code. Rewrite the JSON file as follows:

{
    "modules": {
        "thumbnail": true,
        "readingBookmark": true,
        "outline": true,
        "tools":{
            "Insert": true,
            "Eraser": true,
            "Line": true,
            "Arrow": true,
            "Selection": true, 
            "Underline": true, 
            "Replace": true, 
            "StrikeOut": true, 
            "Note": true, 
            "Highlight": true, 
            "Squiggly": true, 
            "Oval": true,  
            "Freetext": true, 
            "Stamp": true, 
            "Rectangle": true, 
            "Pencil": true
            "Textbox": true, 
            "Polygon": true, 
            "Cloud": true, 
            "Image": true, 
            "Distance": true, 
        }
        "attachment": true,
        "signature": true,
        "search": true,
        "pageNavigation": true,
        "form": true,
        "encryption": true
    }
}

Set the types of annotations that you want to “true”. If you want to remove a specific type of the annotations, just set it to “false”.

Note: If some types of annotations are not in the configuration file, they are also enabled, because the default setting is “true”. For example, if you delete “”highlight“: true,”, it is still available.

Instantiate a UIExtensionsManager object with the configuration file

In section Add UI Extensions Component to build a full-featured PDF Reader (Objective-C) and Add UI Extensions Component to build a full-featured PDF Reader (Swift), we have already introduced how to initialize UIExtensionsManager, and in this way all the built-in UI framework would be loaded by default. In this section, we will provide another method to initialize UIExtensionsManager that uses the configuration file, so that developers can easily customize the feature modules or tools as desired.

Please refer to the following code to instantiate a UIExtensionsManager object with the configuration file.

Note: You should prepare the JSON configuration file, and then add it to your project. Here, we assume that you have already added a JSON file named “uiextensions_config.json”.

In ViewController.swift: (Objective-C)

UIExtensionsManager* extensionsManager;
...
 
// Instantiate a FSPDFViewCtrl object with the size of the entire screen.
FSPDFViewCtrl* pdfViewCtrl;
pdfViewCtrl = [[FSPDFViewCtrl alloc] initWithFrame: [self.view bounds]];
 
// Get the path of the JSON configuration file.
NSString* configPath = [[NSBundle mainBundle] pathForResource:@"uiextensions_config"
ofType:@"json"];
 
// Initialize a UIExtensionsManager object and set it to pdfViewCtrl.
extensionsManager = [[UIExtensionsManager alloc] initWithPDFViewControl:pdfViewCtrl
configuration:[NSData dataWithContentsOfFile:configPath]];
if (nil == extensionsManager) {
    return;
}
pdfViewCtrl.extensionsManager = extensionsManager;

In ViewController.swift: (Swift)

var extensionsManager: UIExtensionsManager!
...
 
// Initialize a FSPDFViewCtrl object with the size of the entire screen
var pdfViewCtrl: FSPDFViewCtrl!
pdfViewCtrl = FSPDFViewCtrl.init(frame:self.view.bounds)
 
// Get the path of the JSON configuration file.
let configPath = Bundle.main.path(forResource: "uiextensions_config", ofType: "json")
var data: Data?
if nil != configPath {
    data = NSData(contentsOfFile: configPath!) as Data?
}
 
// Initialize a UIExtensionsManager object and set it to pdfViewCtrl.
extensionsManager = UIExtensionsManager.init(pdfViewControl: pdfViewCtrl, configuration: data)
if nil == extensionsMgr {
    return
}
pdfViewCtrl.extensionsManager = extensionsManager;

Note: Here, we uses a JSON file to configure the UIExtensions. If you do not want to use JSON file, please refer to the previous section to implement it in code. If you do not want to use a JSON file to configure the UIExtensions, please see the Two formats of the configuration file section to implement it in code.

Customize feature modules and tools through a configuration file

From version 4.0, Foxit PDF SDK for iOS provides a more convenient way to flexibly control and customize the features through a configuration file. Developers can easily choose the features that they want without needing to write any additional code or redesign the app’s UI.

From version 5.0, Foxit PDF SDK for iOS supports customizing the tools which include the Selection tool and the Annotation tools (except Attachment tool) in the built-in Annotation setting bar (See Figure 4-1)through a configuration file. For more details about the configuration file, you can see section “About configuration file”.

Note: To find the Annotation setting bar, just click Comment at the bottom bar, and then click the button below:

Figure 4-1

The above picture does not display all of the annotation tools. You can swipe left on the setting bar to see the other annotation tools.

The configuration file looks like as follows:

{
    "modules": {
        "thumbnail": true,
        "readingBookmark": true,
        "outline": true,
        "tools":{
            "Insert": true,
            "Eraser": true,
            "Line": true,
            "Arrow": true,
            "Selection": true, 
            "Underline": true, 
            "Replace": true, 
            "StrikeOut": true, 
            "Note": true, 
            "Highlight": true, 
            "Squiggly": true, 
            "Oval": true,  
            "Freetext": true, 
            "Stamp": true, 
            "Rectangle": true, 
            "Pencil": true
            "Textbox": true, 
            "Polygon": true, 
            "Cloud": true, 
            "Image": true, 
            "Distance": true, 
        }
        "attachment": true,
        "signature": true,
        "search": true,
        "pageNavigation": true,
        "form": true,
        "encryption": true
    }
}

Please note that only the attachment annotation in the Annotation setting bar is not controlled by the subitems in “tools”. “attachment”: true, ” controls the attachments panel and attachment annotation. If you set it to “false”, both of them will be disabled. If you want to hide “Comment” in the bottom bar, you should set both “annotations” and “attachment” to “false”.

Set the types of tools that you want to “true”, and if you want to remove a specific type of the tools, just set it to “false”.

Note: If all types of the tools in the configuration file are set to “false”, it is equal to ““tools”: false,”. If some types of tools are not in the configuration file, they are also enabled, because the default setting is “true”. For example, if you comment out ““Highlight”: true,”, it is still available.

In this section, we will show you how to customize feature modules and tools in your project. You will find it is extremely easy! You only need to modify the configuration file. Below you can see an example of how to do it.

Note: For your convenience, we will try it in the “complete_pdf_viewer” (Objective-C) and “complete_pdf_viewer_swift” (Swift) demos found in the “samples” folder.

Open the demos in Xcode. Find the configuration file “uiextensions_config.json” under “complete_pdf_viewer\Resource” or “complete_pdf_viewer_swift\Resource”.

Example: Remove “readingbookmark” and “search” feature modules, as well as the “highlight”
and “stamp” annotations.

You only need to update the configuration file as follows:

{
    "modules": {
        "thumbnail": true,
        "readingBookmark": false,
        "outline": true,
        "tools":{
            "Insert": true,
            "Eraser": true,
            "Line": true,
            "Arrow": true,
            "Selection": true, 
            "Underline": true, 
            "Replace": true, 
            "StrikeOut": true, 
            "Note": true, 
            "Highlight": false, 
            "Squiggly": true, 
            "Oval": true,  
            "Freetext": true, 
            "Stamp": false, 
            "Rectangle": true, 
            "Pencil": true
            "Textbox": true, 
            "Polygon": true, 
            "Cloud": true, 
            "Image": true, 
            "Distance": true, 
        }
        "attachment": true,
        "signature": true,
        "search": false,
        "pageNavigation": true,
        "form": true,
        "encryption": true
    }
}

Then, rebuild and run the demo to see the result. Following lists the comparison diagrams:
Before:

After:

The “readingbookmark” and “search” feature modules are removed.

Click Comment at the bottom bar, and then click the button:

Before:

After:

The “highlight” and “stamp” annotations are removed.

stopping point

Customize UI elements through APIs

In version 4.0, Foxit PDF SDK for iOS supports customizing to show or hide the whole top or bottom bar, and from version 5.0, it provides APIs to customize to show or hide a specific panel, the items in the top bar, View setting bar and More Menu view, which is convenient for developers to modify the UI elements in the context of the built-in UI framework.

Note: For your convenience, we will show you how to customize UI elements through APIs in the “complete_pdf_viewer” (Objective-C) and “complete_pdf_viewer_swift” (Swift) demos found in the “samples” folder. We assume that you have not modified the “uiextensions_config.json” file in the demos, which means that all of the built-in UI in the UI Extensions Component are enabled.

Customizing top/bottom bar

  1. Show or hide the top/bottom bar
  2. Show or hide a specific item in the top toolbar

Figure 4-2

Table 4-1 lists the related APIs which are used to customize the top/bottom bar

Table 4-1

(void)enableTopToolbar:(BOOL)isEnabledEnable or disable top toolbar.
(void)enableBottomToolbar:(BOOL)isEnabledEnable or disable bottom toolbar.
(void)setTopToolbarItemHiddenWithTag:
(NSUInteger)itemTag hidden:(BOOL)isHidden
Show or hide the item in the top bar.

The value of the parameter “itemTag” in setTopToolbarItemHiddenWithTag interface can be set as follows, which maps the features in the top bar.

Item nameitemTagNSUInteger
BackFS_TOPBAR_ITEM_BACK_TAG101
BookmarkFS_TOPBAR_ITEM_BOOKMARK_TAG100
SearchFS_TOPBAR_ITEM_SEARCH_TAG 103
MoreFS_TOPBAR_ITEM_MORE_TAG 102

In the following examples, we will show you how to customize the top/bottom bar through APIs in the “complete_pdf_viewer” (Objective-C) and “complete_pdf_viewer_swift” (Swift) demos found in the “samples” folder.

Open the demos in Xcode. Add the sample code to the “ViewController.m” (Objective-C) or “ViewController.swift” (Swift) (after the code that initializes UIExtensionsManager).

Example 1: Hide the whole top bar.

Objective-C:

[self.extensionsMgr enableTopToolbar:false];

Swift:

extensionsMgr.enableTopToolbar(false)

Before:

After:

Example 2: Hide the whole bottom bar.

Objective-C:

[self.extensionsMgr enableBottomToolbar:false];

Swift:

extensionsMgr.enableBottomToolbar(false)

Before:

After:

Example 3: Hide the more menu item in the top bar.

Objective-C:

[self.extensionsMgr setTopToolbarItemHiddenWithTag:FS_TOPBAR_ITEM_MORE_TAG hidden:YES];

Swift:

extensionsMgr.setTopToolbarItemHiddenWithTag(UInt(FS_TOPBAR_ITEM_MORE_TAG), hidden: true)

Before:

After:

For other items in the top bar, you can refer to the above example, and just need to change the value of the parameter “itemTag” in setTopToolbarItemHiddenWithTag interface.

To show one of the UI elements in the top bar, just set the opposite value for “true” and “false” in the above examples.

Customizing to show/hide a specific Panel

To show or hide a specific panel (See Figure 4-3, includes “Reading Bookmarks”, “Outline”, “Annotations” and “Attachments” panels, just clicks List at the bottom bar to find it), you only need to use the following API:

(void)setPanelHidden:(BOOL)isHidden type:(FSPanelType)type

Figure 4-3

Note: To show or hide a specific panel through APIs, please mark sure the corresponding features in the configuration file is set to “true”. Otherwise, the API settings will not have any effect.

In this section, we only give an example to show you how to show or hide a specific panel through APIs in the “complete_pdf_viewer” (Objective-C) and “complete_pdf_viewer_swift” (Swift) demos found in the “samples” folder. Just take the “Outline” panel as an example, and for others panels, you only need to change the FSPanelType. The corresponding relation between panels and FSPanelType are as follows:

PanelFSPanelType
Reading BookmarksFSPanelTypeReadingBookmark
OutlineFSPanelTypeOutline
AnnotationsFSPanelTypeAnnotation
Attachments FSPanelTypeAttachment

Open the demos in Xcode. Add the sample code to the “ViewController.m” (Objective-C) or “ViewController.swift” (Swift) (after the code that initializes UIExtensionsManager).

Example: Hide the “Outline” panel.

Objective-C:

[self.extensionsMgr.panelController setPanelHidden:true type:FSPanelTypeOutline];

Swift:

extensionsMgr.panelController.setPanelHidden(true, type: .outline)

Before:

After:

For Reading Bookmarks, Annotations, and Attachments panels, you only need to change the FSPanelType. Just try it.

Customizing to show/hide the UI elements in the View setting bar

To show or hide the UI elements in the View setting bar (See Figure 4-4, just clicks View at the bottom bar to find it), you only need to use the following API:

(void)setItem:(SettingItemType)itemType hidden:(BOOL)hidden;

Figure 4-4

The value of the parameter “itemType” can be set as follows, which maps the items in the View setting bar.

itemitemType
Single page modeSINGLE
Continuous page modeCONTINUOUS
Thumbnail THUMBNAIL
Auto-Brightness BRIGHTNESS
Night modeNIGHTMODEL
Reflow modeREFLOW
Screen lockLOCKSCREEN
Crop modeCROPPAGE
Facing mode (only for iPad)DOUBLEPAGE

In this section, we only take “Reflow” item as an example to show you how to show or hide the UI elements in the View setting bar through APIs in the “complete_pdf_viewer” (Objective-C) and “complete_pdf_viewer_swift” (Swift) demos found in the “samples” folder. For other UI elements, you only need to change the “itemType“.

Open the demos in Xcode. Add the sample code to the “ViewController.m” (Objective-C) or “ViewController.swift” (Swift) (after the code that initializes UIExtensionsManager).

Example: Hide the “Reflow” item in the View setting bar.

Objective-C:

[self.extensionsMgr.settingBar setItem:REFLOW hidden:YES];

Swift:

extensionsMgr.settingBar.setItem(.REFLOW, hidden: true)

Before:

After:

For other items in the View setting bar, you can refer to the above example, and just need to change the value of the parameter “itemType” in setItem interface.

To show one of the UI elements in the View setting bar, just set the “hidden” to “false” in the above example.

Customizing to show/hide the UI elements in the More Menu view

To show or hide the UI elements in the More Menu view (See Figure 4-5, just click at the menu icon at the right top bar to find it), you can use the following APIs listed in the Table 4-2.

Figure 4-5

The value of the parameter “groupTag” in the setMoreViewItemHiddenWithGroup interface can be set as follows:

groupTagNSUInteger
TAG_GROUP_FILE1
TAG_GROUP_PROTECT 4
TAG_GROUP_FORM 7

Table 4-2

(void)setMoreViewItemHiddenWithGroup:
(NSUInteger)groupTag hidden:(BOOL)isHidden
Set the enabled state of group
according to "groupTag".
(void)setMoreViewItemHiddenWithGroup:
(NSUInteger)groupTag andItemTag:(NSUInteger)itemTag
hidden:(BOOL)isHidden
Set the enabled state of item
according to "groupTag" and
"itemTag".

groupTagitemTagNSUInteger
TAG_GROUP_FILETAG_ITEM_FILEINFO10
TAG_GROUP_FILETAG_ITEM_REDUCEFILESIZE11
TAG_GROUP_PROTECT TAG_ITEM_PASSWORD17
TAG_GROUP_FORM
TAG_ITEM_RESETFORM24
TAG_GROUP_FORM
TAG_ITEM_IMPORTFORM25
TAG_GROUP_FORM
TAG_ITEM_EXPORTFORM26

Note: If you want to show or hide an itemTag, please make sure the corresponding groupTag has not been hidden. Otherwise, the settings will not have any effect.

In this section, we only take “TAG_GROUP_FILE” (File in the view) and “TAG_ITEM_FILEINFO” (File Information in the view) as an example to show you how to show or hide the UI elements in the More Menu view through APIs in the “complete_pdf_viewer” (Objective-C) and “complete_pdf_viewer_swift” (Swift) demos found in the “samples” folder. For other UI elements, you can refer to the following examples and only need to change the parameter value in the setMoreViewItemHiddenWithGroup interfaces.

Open the demos in Xcode. Add the sample code to the “ViewController.m” (Objective-C) or “ViewController.swift” (Swift) (after the code that initializes UIExtensionsManager).

Example 1: Hide the “File” in the More Menu view.

Objective-C:

[self.extensionsMgr.more setMoreViewItemHiddenWithGroup:(TAG_GROUP_FILE) hidden:YES];

Swift:

self.extensionsMgr.more.setMoreViewItemHiddenWithGroup(UInt(TAG_GROUP_FILE), hidden: true)

Before:

After:

Example 2: Hide the “File Information” in the More Menu view.

Objective-C:

[self.extensionsMgr.more setMoreViewItemHiddenWithGroup:TAG_GROUP_FILE andItemTag:TAG_ITEM_FILEINFO hidden:YES];

Swift:

self.extensionsMgr.more.setMoreViewItemHiddenWithGroup(UInt(TAG_GROUP_FILE), andItemTag: UInt(TAG_ITEM_FILEINFO), hidden: true)

Before:

After:

For other items in the More Menu view, you can refer to the above examples, and just need to change the parameter value in the setMoreViewItemHiddenWithGroup interfaces.

To show one of the UI elements in the More Menu view, just set the “hidden” to “false” in the above examples.

Customize UI implementation through source code

In the previous sections, we have introduced how to customize the UI elements through APIs or configuration file in detail. Those changes are in the context of the built-in UI framework of Foxit PDF SDK for iOS. If you do not want to use the ready-made UI framework, you can redesign it through modifying the source code of the UI Extensions Component.

There is one thing to take note of. The source code of the UI Extensions Component is written in Objective-C, so you need to use Objective-C to modify the UI layout. If you are a Swift developer and not already familiar with Objective-C, you might only be able to customize the UI appearance that does not need writing code, such as icons and other UI resources.

To customize the UI implementation, you need to follow these steps:

First, add the following files into your app.

  • FoxitRDK.framework – The framework that includes the Foxit PDF SDK for iOS dynamic library and associated header files. It can be found in the “libs” folder.
  • uiextensions project – It is an open source library that contains some ready-to-use UI module implementations, which can help developers rapidly embed a fully functional PDF reader into their iOS app. Of course, developers are not forced to use the default UI, they can freely customize and design the UI for their specific apps through the “uiextensions” project. It can be found in the “libs/uiextensions_src” folder.

Second, find the specific code or images related to the UI that you want to customize in the uiextensions project, then modify them based on your requirements.

Now, for your convenience, we will show you how to customize the UI implementation in the “viewer_ctrl_demo” project found in the “samples” folder.

UI Customization Example

Step 1: Add the uiextensions project into the demo.

Note: We will add the uiextensions project to the demo which is convenient for us to see the custom results. The demo already includes FoxitRDK.framework, so we just need to add the uiextensions project.

Load the “viewer_ctrl_demo” in XCode. Drag-and-drop “uiextensions.xcodeproj” found in the “libs/uiextensions_src” of the download package into the “viewer_ctrl_demo” project as shown in Figure 4-6.

Figure 4-6

Then, it will pop up a dialog box which prompts you whether to save the project in a new workspace as shown in Figure 4-7. Click Save.

Figure 4-7

Save the workspace to the “samples” folder, and name “custom_viewer” as shown in Figure 4-8. Click Save.

Figure 4-8

Now, the workspace looks like the Figure 4-9.

Figure 4-9

Congratulations! You have completed the first step

Step 2: Find and modify the code or images related to the UI that you want to customize.

Now we will show you a simple example that changes one button’s icon in the search panel as shown in Figure 4-10.

Figure 4-10

To replace the icon we only need to find the place which stores the icon for this button, then use another icon with the same name to replace it.

Note: Foxit PDF SDK for iOS provides three sets of icons for different devices to make sure that your apps can run smoothly on every device. There are three folders used to store the image resources as follows:

  • Image: used for older devices with non-Retina display (e.g. iPad 2).
  • Image2x: used for iPhone 4/4s/5/5s/6/6s/7/7s/8.
  • Image3x: used for iPhone 6/6s/7/7s/8 Plus, which has the highest resolution.

An iPhone 8 Simulator will be used as an example to run the demo. In the project, click “Resource -> png -> image2x -> Search” as shown in Figure 4-11. It’s easy to find the image that we want to replace. The resource files are stored according to the features, so you can locate the related code through the icon’s name.

Figure 4-11

Right now, just replace “search_showlist@2x.png” with your own icon in the “libs/uiextensions_src/uiextensions/Resource/png/image2x” folder. For example, we use the icon of the top search button (search@2x.png) to replace it.

After replacing, firstly build and run the uiextensions_aggregate project as shown in Figure 4-12.

Figure 4-12

Here, we build and run uiextensions_aggregate, then the generated library will include the libraries for both simulator and iOS device. If you choose uiextensions and run it on a simulator, then the generated library is a simulator library which can only be used for simulator.

Note: The “libFoxitRDKUIExtensions.a” library in the “libs” folder of the download package is a universal static library which includes the libraries for both simulator and iOS device. It will be overwritten after building the “uiextensions” project successfully. In the “uiextension” project, it has already added the scripts to generate the universal static library as shown in Figure 4-12.

Then build and run the “viewer_ctrl_demo” project. After building successfully, try the search feature and we can see that the icon of the bottom search button has changed as shown in Figure 4-13.

Figure 4-13

This is just a simple example to show how to customize the UI implementation. You can refer to it and feel free to customize and design the UI for your specific apps through the uiextensions project.

Creating a Custom Tool

With Foxit PDF SDK for iOS, creating a custom tool is a simple process. There are several tools implemented in the UI Extensions Component already. These tools can be used as a base for developers to build upon or use as a reference to create a new tool. In order to create your own tool quickly, we suggest you take a look at the uiextension project found in the “libs” folder.

To create a new tool, the most important step is to declare a class that implements the “IToolHandler” interface.

In this section, we will make a Regional Screenshot Tool to show how to create a custom tool with Foxit PDF SDK for iOS. This tool can help the users who only want to select an area in a PDF page to capture, and then save it as an image. Now, let’s do it

Create a Regional Screenshot Tool in Objective-C

For convenience, we will build this tool based on the “viewer_ctrl_demo” project found in the “samples” folder. Steps required for implementing this tool are as follows:

  • Create a class named ScreenCaptureToolHandler that implements the “IToolHandler” interface.
  • Handle onPageViewLongPress and onDraw events.
  • Instantiate a ScreenCaptureToolHandler object, and then register it to the extensions manager.
  • Set the ScreenCaptureToolHandler object as the current tool handler

Step 1: Create a class named ScreenCaptureToolHandler that implements the “IToolHandler” interface.

a) Load the “viewer_ctrl_demo” project in Xcode. Create a class named “ScreenCaptureToolHandler” in the “Source” folder, and create the corresponding header file.

b) Let the ScreenCaptureToolHandler class implement the IToolHandler interface as follows:

 @interface ScreenCaptureToolHandler : NSObject<IToolHandler>

Step 2: Handle onTouchEvent and onDraw events.

Update ScreenCaptureToolHandler.h as follows:

 #import <Foundation/Foundation.h>
#import <FoxitRDK/FSPDFViewControl.h>
#import "../../../libs/uiextensions_src/uiextensions/UIExtensionsManager.h"
@protocol IToolHandler;
@class TaskServer;
 
@interface ScreenCaptureToolHandler : NSObject
 
- (instancetype)initWithUIExtensionsManager:(UIExtensionsManager*)extensionsManager taskServer:(TaskServer*)taskServer;
@end

Update ScreenCaptureToolHandler.h as follows:

 #import "ScreenCaptureToolHandler.h"
#import <ImageIO/ImageIO.h>
#import <ImageIO/CGImageDestination.h>
#import <MobileCoreServices/UTCoreTypes.h>
 
@interface ScreenCaptureToolHandler ()
 
@end
 
@implementation ScreenCaptureToolHandler {
    UIExtensionsManager* _extensionsManager;
    FSPDFViewCtrl* _pdfViewCtrl;
    TaskServer* _taskServer;
 
    CGPoint startPoint;
    CGPoint endPoint;
 
}
@synthesize type;
 
- (instancetype)initWithUIExtensionsManager:(UIExtensionsManager*)extensionsManager taskServer:(TaskServer*)taskServer
{
    self = [super init];
    if (self) {
        _extensionsManager = extensionsManager;
        _pdfViewCtrl = extensionsManager.pdfViewCtrl;
        _taskServer = taskServer;
    }
    return self;
}
 
-(NSString*)getName
{
    return @" ";
}
 
-(BOOL)isEnabled
{
    return YES;
}
 
-(void)onActivate
{
 
}
 
-(void)onDeactivate
{
 
}
 
// Save the image to a specified path.
- (void)saveJPGImage:(CGImageRef)imageRef path:(NSString *)path
{
    NSURL *fileURL = [NSURL fileURLWithPath:path];
    CGImageDestinationRef dr = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeJPEG , 1, NULL);
 
    CGImageDestinationAddImage(dr, imageRef, NULL);
    CGImageDestinationFinalize(dr);
 
    CFRelease(dr);
}
 
// Handle the PageView Gesture and Touch event
- (BOOL)onPageViewLongPress:(int)pageIndex recognizer:(UILongPressGestureRecognizer *)recognizer
{
    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        startPoint = [recognizer locationInView:[_pdfViewCtrl getPageView:pageIndex]];
        endPoint = startPoint;
    }
    else if (recognizer.state == UIGestureRecognizerStateChanged)
    {
 
        endPoint = [recognizer locationInView:[_pdfViewCtrl getPageView:pageIndex]];
 
        // Refresh the page view, then the onDraw event will be triggered.
        [_pdfViewCtrl refresh:pageIndex];
    }
    else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled)
    {
        // Get the size of the Rect.
        CGSize size = {fabs(endPoint.x-startPoint.x), fabs(endPoint.y-startPoint.y)};
        CGPoint origin = {startPoint.x<endPoint.x?startPoint.x:endPoint.x, startPoint.y<endPoint.y?startPoint.y:endPoint.y};
        // Get the Rect.
        CGRect rect = {origin, size};
 
        int newDibWidth = rect.size.width;
        int newDibHeight = rect.size.height;
        if (newDibWidth < 1 || newDibHeight < 1)
        {
            return YES;
        }
 
        UIView* pageView = [_pdfViewCtrl getPageView:pageIndex];
        CGRect bound = pageView.bounds;
 
        // Create a bitmap with the size of the selected area.
        int imgSize = newDibWidth*newDibHeight*4;
        void* pBuff = malloc(newDibWidth*newDibHeight*4);
        FSBitmap* fsbitmap = [FSBitmap create:newDibWidth height:newDibHeight format:e_dibArgb buffer:pBuff pitch:newDibWidth*4];
        [fsbitmap fillRect:0xFFFFFFFF rect:nil];
        FSRenderer* fsrenderer = [FSRenderer create:fsbitmap rgbOrder:YES];
        FSPDFPage* page = [_pdfViewCtrl.currentDoc getPage:pageIndex];
 
        // Calculate the display matrix.
        FSMatrix* fsmatrix = [page getDisplayMatrix:-rect.origin.x yPos:-rect.origin.y xSize:bound.size.width ySize:bound.size.height rotate:0];
 
        // Set the render content, then start to render the selected area to the bitmap.
        [fsrenderer setRenderContent:e_renderPage|e_renderAnnot];
        [fsrenderer startRender:page matrix:fsmatrix pause:nil];
        [fsrenderer continueRender];
 
        // Convert FSBitmap to CGImage.
        CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pBuff, imgSize, nil);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault|kCGImageAlphaLast;
 
        CGImageRef image = CGImageCreate(newDibWidth,newDibHeight, 8, 32, newDibWidth * 4,
                                         colorSpace, bitmapInfo,
                                         provider, NULL, YES, kCGRenderingIntentDefault);
 
        // Save the image to a specified path.
        NSString* jpgPath =@"/Users/Foxit/Desktop/ScreenCapture.jpg";
        [self saveJPGImage:image path:jpgPath];
 
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@""
                                                       message:@" The selected area was saved as a JPG stored in the /Users/Foxit/Desktop/ScreenCapture.jpg" delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"OK") otherButtonTitles:nil];
        [alert show];
 
        return YES;
    }
    return YES;
}
 
// Handle the drawing event.
-(void)onDraw:(int)pageIndex inContext:(CGContextRef)context
{
    if ([_extensionsManager getCurrentToolHandler] != self) {
        return;
    }
 
    CGContextSetLineWidth(context, 2);
    CGContextSetLineCap(context, kCGLineCapSquare);
    UIColor *color = [UIColor redColor];
    CGContextSetStrokeColorWithColor(context, [color CGColor]);
    CGPoint points[] = {startPoint,CGPointMake(endPoint.x, startPoint.y),endPoint,CGPointMake(startPoint.x, endPoint.y)};
    CGContextAddLines(context,points,4);
    CGContextClosePath(context);
    CGContextStrokePath(context);
}
 
- (BOOL)onPageViewTap:(int)pageIndex recognizer:(UITapGestureRecognizer *)recognizer
{
    return NO;
}
 
- (BOOL)onPageViewPan:(int)pageIndex recognizer:(UIPanGestureRecognizer *)recognizer
{
    return NO;
 
}
 
- (BOOL)onPageViewShouldBegin:(int)pageIndex recognizer:(UIGestureRecognizer *)gestureRecognizer
{
    if (self != [_extensionsManager getCurrentToolHandler]) {
        return NO;
    }
    return YES;
}
 
 
- (BOOL)onPageViewTouchesBegan:(int)pageIndex touches:(NSSet*)touches withEvent:(UIEvent*)event
{
    return NO;
}
 
- (BOOL)onPageViewTouchesMoved:(int)pageIndex touches:(NSSet *)touches withEvent:(UIEvent *)event
{
    return NO;
}
 
- (BOOL)onPageViewTouchesEnded:(int)pageIndex touches:(NSSet *)touches withEvent:(UIEvent *)event
{
    return NO;
}
 
- (BOOL)onPageViewTouchesCancelled:(int)pageIndex touches:(NSSet *)touches withEvent:(UIEvent *)event
{
    return NO;
}
 
@end

Note: In the above code, you should specify an existing path to save the image. Here, the path is “@”/Users/Foxit/Desktop/ScreenCapture.jpg””, please replace it with a valid path.

Step 3: In ViewController.m, instantiate a ScreenCaptureToolHandler object and then register it to the UIExtensionsManager.

#import "ScreenCaptureToolHandler.h"
...
 
@property (nonatomic, strong) ScreenCaptureToolHandler* screencaptureToolHandler;
...
 
self.screencaptureToolHandler = [[[ScreenCaptureToolHandler alloc] initWithUIExtensionsManager: 
self.extensionsManager taskServer:nil] 
[self.extensionsManager registerToolHandler:self.screencaptureToolHandler];

Step 4: In ViewController.m, set the ScreenCaptureToolHandler object as the current tool handler.

Register the Doc event listener.

@interface ViewController ()

Set the current tool handler in the onDocOpened function:

- (void)onDocOpened:(FSPDFDoc *)document error:(int)error { 
       [self.extensionsManager setCurrentToolHandler:self.screenCaptureToolHandler]; 
}

Now, we have really finished creating a custom tool in Objective-C, build and run the demo. An iPhone 7 Simulator will be used as an example to run the project. After building the demo successfully, long press and select a rectangular area, and then a message box will be popped up as shown in Figure 5-1. It shows where the image (selected area) was saved to.

Figure 5-1

In order to verify whether the tool captures the selected area successfully, we need to find the screenshot. Go to “desktop”, we can see the image as shown in Figure 5-2.

 

Figure 5-2

As you can see we have successfully created a Regional Screenshot Tool in Objective-C. This is just an example to show how to create a custom tool with Foxit PDF SDK for iOS. You can refer to it or the demos to develop the tools you want.

Create a Regional Screenshot Tool in Swift

For convenience, we will build this tool based on the “viewer_ctrl_demo_swift” project found in the “samples\swift” folder. Steps required for implementing this tool are as follows:

  • Create a class named ScreenCaptureToolHandler that implements the “IToolHandler” interface.
  • Handle onPageViewLongPress and onDraw events.
  • Instantiate a ScreenCaptureToolHandler object, and then register it to the extensions manager.
  • Set the ScreenCaptureToolHandler object as the current tool handler

Step 1: Create a class named ScreenCaptureToolHandler that implements the “IToolHandler” interface.

a) Load the “viewer_ctrl_demo_swift” project in Xcode. Create a class named “ScreenCaptureToolHandler” in the “Source” folder.

b) Let the ScreenCaptureToolHandler class implement the IToolHandler interface as follows:

class ScreenCaptureToolHandler: NSObject, IToolHandler { }

Step 2: Handle onTouchEvent and onDraw events.

Update ScreenCaptureToolHandler.swift as follows:

import Foundation
import MobileCoreServices
import ImageIO
 
class ScreenCaptureToolHandler: NSObject, IToolHandler {
    public var type: FS_ANNOTTYPE
 
    var extensionManager: UIExtensionsManager!
    var pdfViewCtrl: FSPDFViewCtrl!
 
    var startPoint = CGPoint()
    var endPoint = CGPoint()
 
    init(extensionsManager: UIExtensionsManager) {
        self.extensionManager = extensionsManager
        self.pdfViewCtrl = extensionsManager.pdfViewCtrl
        self.type = e_annotUnknownType
        super.init()
    }
 
    func getName() -> String {
        return " "
    }
 
    func isEnabled() -> Bool {
        return true
    }
 
    func onActivate() {
    }
 
    func onDeactivate() {
    }
 
    // Save the image to a specified path.
    func saveJPGImage(imageRef: CGImage, path: String) {
        let fileURL: CFURL = NSURL.fileURL(withPath: path) as CFURL
        let dr = CGImageDestinationCreateWithURL(fileURL, kUTTypeJPEG, 1, nil)!
        CGImageDestinationAddImage(dr, imageRef, nil)
        CGImageDestinationFinalize(dr)
    }
 
    // Handle the PageView Gesture and Touch event
    func onPageViewLongPress(_ pageIndex: Int32, recognizer: UILongPressGestureRecognizer!) -> Bool {
 
        if recognizer.state == UIGestureRecognizerState.began {
            startPoint = recognizer.location(in: pdfViewCtrl.getPageView(pageIndex))
            endPoint = startPoint
        }
        else if recognizer.state == UIGestureRecognizerState.changed {
 
            endPoint = recognizer.location(in: pdfViewCtrl.getPageView(pageIndex))
 
            // Refresh the page view, then the onDraw event will be triggered.
            pdfViewCtrl.refresh(pageIndex)
        }
        else if recognizer.state == UIGestureRecognizerState.ended || recognizer.state == UIGestureRecognizerState.cancelled {
 
            // Get the size of the Rect.
            let size = CGSize(width: fabs(endPoint.x - startPoint.x), height: fabs(endPoint.y - startPoint.y))
            let origin = CGPoint(x: (startPoint.x < endPoint.x) ? startPoint.x : endPoint.x, y: (startPoint.y<endPoint.y) ? startPoint.y : endPoint.y)
            // Get the Rect.
            let rect = CGRect(origin: origin, size: size)
 
            let newDibwidth = rect.size.width
            let newDibHeight = rect.size.height
            if newDibwidth < 1 || newDibHeight < 1 {
                return true
            }
 
            let pageView = pdfViewCtrl.getPageView(pageIndex)
            let bound = pageView?.bounds
 
            // Create a bitmap with the size of the selected area.
            let imgSize = newDibwidth * newDibHeight * 4
            let capacity: Int = Int(newDibwidth) * Int(newDibHeight) * 4
            let pBuff = UnsafeMutablePointer.allocate(capacity: capacity)
            let pitch: Int = Int(newDibwidth) * 4
            let fsbitmap = FSBitmap.create(Int32(newDibwidth), height: Int32(newDibHeight), format: e_dibArgb, buffer: pBuff, pitch: Int32(pitch))
            fsbitmap?.fillRect(0xFFFFFFFF, rect: nil)
            let fsrenderer = FSRenderer.create(fsbitmap, rgbOrder: true)
            let page = pdfViewCtrl.currentDoc.getPage(pageIndex)
 
            // Calculate the display matrix.
            let fsmatrix = page?.getDisplayMatrix(-(Int32)(rect.origin.x), yPos: -(Int32)(rect.origin.y), xSize: Int32((bound?.size.width)!), ySize: Int32((bound?.size.height)!), rotate: FS_ROTATION(rawValue: e_rotation0.rawValue))
 
            // Set the render content, then start to render the selected area to the bitmap.
            fsrenderer?.setRenderContent(e_renderPage.rawValue | e_renderAnnot.rawValue)
            fsrenderer?.startRender(page, matrix: fsmatrix, pause: nil)
            fsrenderer?.continueRender()
 
            // Convert FSBitmap to CGImage.
            let releaseData: CGDataProviderReleaseDataCallback = {
                (info: UnsafeMutableRawPointer?, data:UnsafeRawPointer, size:Int) -> Void in
            }
 
            let provider: CGDataProvider = CGDataProvider(dataInfo: nil, data: pBuff, size: Int(imgSize), releaseData: releaseData)!
            let colorSpace = CGColorSpaceCreateDeviceRGB()
            let bitmapInfo: CGBitmapInfo = .byteOrderMask
 
            let image = CGImage(width: Int(newDibwidth), height: Int(newDibHeight), bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: Int(newDibwidth) * 4, space: colorSpace, bitmapInfo: bitmapInfo, provider: provider, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
 
            // Save the image to a specified path.
            let jpgPath = "/Users/Foxit/Desktop/ScreenCapture.jpg"
            self.saveJPGImage(imageRef: image!, path: jpgPath)
 
            let alert = UIAlertView(title: "", message: " The selected area was saved as a JPG stored in the /Users/Foxit/Desktop/ScreenCapture.jpg", delegate: nil, cancelButtonTitle: NSLocalizedString("OK", comment: "OK"))
            alert.show()
            return true
        }
        return true
    }
 
    // Handle the drawing event.
    func onDraw(_ pageIndex: Int32, in context: CGContext!) {
        context.setLineWidth(CGFloat(2))
        context.setLineCap(.square)
        let color = UIColor.red
        context.setStrokeColor(color.cgColor)
        let points = [startPoint, CGPoint(x: CGFloat(endPoint.x), y: CGFloat(startPoint.y)), endPoint, CGPoint(x: CGFloat(startPoint.x), y: CGFloat(endPoint.y))]
        context.addLines(between: points)
        context.closePath()
        context.strokePath()
    }
 
    func onPageViewTap(_ pageIndex: Int32, recognizer: UITapGestureRecognizer!) -> Bool {
        return false
    }
 
    func onPageViewPan(_ pageIndex: Int32, recognizer: UIPanGestureRecognizer!) -> Bool {
        return false
    }
 
    func onPageViewShouldBegin(_ pageIndex: Int32, recognizer gestureRecognizer: UIGestureRecognizer!) -> Bool {
        return true
    }
 
    func onPageViewTouchesBegan(_ pageIndex: Int32, touches: Set, with event: UIEvent) -> Bool {
        return false
    }
 
    func onPageViewTouchesMoved(_ pageIndex: Int32, touches: Set, with event: UIEvent) -> Bool {
        return false
    }
 
    func onPageViewTouchesEnded(_ pageIndex: Int32, touches: Set, with event: UIEvent) -> Bool {
        return false
    }
 
    func onPageViewTouchesCancelled(_ pageIndex: Int32, touches: Set, with event: UIEvent) -> Bool {
        return false
    }
}

Note: In the above code, you should specify an existing path to save the image. Here, the path is  “/Users/Foxit/Desktop/ScreenCapture.jpg” , please replace it with a valid path.

Step 3: In ViewController.swift, istantiate a ScreenCaptureToolHandler object and then register it to the UIExtensionsManager.

var screencaptureToolHandler: ScreenCaptureToolHandler!
...
self.screencaptureToolHandler = ScreenCaptureToolHandler.init(extensionsManager:
self.extensionsManager)
self.extensionsManager.register(self.screencaptureToolHandler)

Step 4:  In ViewController.swift, set the ScreenCaptureToolHandler object as the current tool handler.

Register the Doc event listener

class ViewController: UIViewController, UISearchBarDelegate, ISearchEventListener, IDocEventListener

Set the current tool handler in the onDocOpened function:

func onDocOpened(_ document: FSPDFDoc, error: Int32) { 
    self.extensionsManager.currentToolHandler = self.screenCaptureToolHandler 
}

Now, we have really finished creating a custom tool in Swift. Then, build and run the demo. After building the demo successfully, long press and select a rectangular area, and then a message box will be popped up (refer to Figure 5-1). Go to “desktop”, we will see the screenshot (refer to Figure 5-2).

This is just an example to show how to create a custom tool in Swift with Foxit PDF SDK for iOS. You can refer to it or the demos to develop the tools you want.

 

Technical Support

Reporting Problems

Foxit offers 24/7 support for its products and are fully supported by the PDF industry’s largest development team of support engineers. If you encounter any technical questions or bug issues when using Foxit PDF SDK for iOS, please submit the problem report to the Foxit support team at http://tickets.foxitsoftware.com/create.php. In order to better help you solve the problem, please provide the following information:

  • Contact details
  • Foxit PDF SDK for iOS product and version
  • Your Operating System and IDE version
  • Detailed description of the problem
  • Any other related information, such as log file or error screenshot

Contact Information

You can contact Foxit directly, please use the contact information as follows:

Foxit Support:

Sales Contact:

  • Phone: 1-866-680-3668
  • Email: sales@foxitsoftware.com

Support & General Contact:

  • Phone: 1-866-MYFOXIT or 1-866-693-6948
  • Email: support@foxitsoftware.com

 

Updated on June 20, 2018

Was this article helpful?

Related Articles