Introduction
MuPDF Android App Kit
MuPDF iOS App Kit
Download App Kit

File Operations

There are a number of file operations available against a document, an application developer should only be required to implement these if using the Custom UI.

Save

Saving a document only needs to be invoked if there are changes made to a document. As such an application developer can verify if changes have been made or not and act accordingly. The MuPDFDKBasicDocumentViewController session can be used to save the document with a callback method for the completion.

Swift
self.session.saveDocumentAnd(onCompletion: { (result:ARDKSaveResult,
                                               error:ARError) in
    self.updateUI() // refresh the UI on completion

    switch result {

        case ARDKSave_Succeeded:

        break

        case ARDKSave_Cancelled:

        break

        case ARDKSave_Error:

        break

        default:

        break
    }
})
Objective C
[self.session saveDocumentAndOnCompletion:^(ARDKSaveResult result,
                                            ARError err) {
    [self updateUI]; // refresh the UI on completion

    switch (result)
    {
        case ARDKSave_Succeeded:

        break;

        case ARDKSave_Cancelled:

        break;

        case ARDKSave_Error:

        break;

        default:

        break;
    }
}];

Save As

An application developer should provide the new filename and use the saveTo method of the MuPDFDKBasicDocumentViewController session to save documents with a new name.

Swift
let fileName:String = "new-filename.pdf";
let existingPath:NSString = session.fileState.absoluteInternalPath as NSString
let newPath:String = "\(existingPath.deletingLastPathComponent)/\(fileName)"

session.save(to: newPath, completion: { (result:ARDKSaveResult,
                                          error:ARError) in
    self.updateUI()

    switch result {

        case ARDKSave_Succeeded:

        break

        case ARDKSave_Cancelled:

        break

        case ARDKSave_Error:

        break

        default:

        break
    }
})
Objective C
NSString *fileName = "new-filename.pdf";
NSString *newPath = [[self.session.fileState.absoluteInternalPath
    stringByDeletingLastPathComponent] stringByAppendingPathComponent:fileName];
[self.session saveTo:newPath completion:^(ARDKSaveResult res, ARError err) {
    switch (res)
    {
        case ARDKSave_Succeeded:
            break;

        case ARDKSave_Cancelled:
        case ARDKSave_Error:
            NSLog(@"Save failed with error: %d", err);
            break;
    }
}];

Print

Application developers should firstly instantiate a native UIPrintInteractionController and pass through a page renderer with ARDKPrintPageRenderer which has been initialized with the current document.

Swift
let printController:UIPrintInteractionController =
UIPrintInteractionController.shared
let pageRenderer:ARDKPrintPageRenderer =
ARDKPrintPageRenderer(document:self.doc)
printController.printPageRenderer = pageRenderer

printController.present(animated: true,
    completionHandler: { (printInteractionController:UIPrintInteractionController,
        completed:Bool,
        error:Error?) in
    if error != nil {
        print("Print failed due to error:\(error!)")
    }
})
Objective C
UIPrintInteractionController *printController =
[UIPrintInteractionController sharedPrintController];
ARDKPrintPageRenderer *pageRenderer =
[[ARDKPrintPageRenderer alloc] initWithDocument:self.doc];
printController.printPageRenderer = pageRenderer;
[printController presentAnimated:YES
    completionHandler:^(
        UIPrintInteractionController * _Nonnull printInteractionController,
        BOOL completed,
        NSError * _Nullable error) {
    if (error) {
        NSLog(@"Print failed due to error %@", error);
    }
}];

Searching can be made forward or backward from a defined point in the document. Successful searching automatically highlights the next instance of a found string and moves the document selection to that point.

NOTE
Search is case-insensitive.

Swift
// Starts searching the document from the first page
self.doc.setSearchStartPage(0, offset: .zero)

// search forward from this point for the word "hello" and
// highlight the found occurrence
self.doc.search(for: "hello",
      in:MuPDFDKSearch_Forwards,
      onEvent:{event,page,area in

        switch event {

            case MuPDFDKSearch_Progress:
                // If we had a progress indicator, we could set it here according
                // to where page is between 0 and self.doc.pageCount
            break

            case MuPDFDKSearch_Found:
                self.updateUI()
                // Pan to show the found occurrence
                self.docViewController.showArea(area, onPage: page)
            break

            case MuPDFDKSearch_NotFound:
                self.updateUI()
                // Could ask the user here whether to restart the search from
                // the start of the document
            break

            case MuPDFDKSearch_Cancelled:
                self.updateUI()
            break

            case MuPDFDKSearch_Error:
                self.updateUI()
            break

            default:
                self.updateUI()
            break

        }
})
Objective C
// Starts searching the document from the first page
[self.doc setSearchStartPage:0 offset:CGPointZero];

// search forward from this point for the word "hello" and
// highlight the found occurrence
[self.doc searchFor:"hello"
        inDirection:MuPDFDKSearch_Forwards
          onEvent:^(MuPDFDKSearchEvent event, NSInteger page, CGRect area) {
    switch (event)
    {
        case MuPDFDKSearch_Progress:
            // If we had a progress indicator, we could set it here according
            // to where page is between 0 and self.doc.pageCount
            break;

        case MuPDFDKSearch_Found:
            [self updateUI];
            // Pan to show the found occurrence
            [self.docViewController showArea:area onPage:page];
            break;

        case MuPDFDKSearch_NotFound:
            [self updateUI];
            // Could ask the user here whether to restart the search from
            // the start of the document
            break;

        case MuPDFDKSearch_Cancelled:
            [self updateUI];
            break;

        case MuPDFDKSearch_Error:
            [self updateUI];
            break;
    }
}];

FileState

The FileState protocol should be adhered to if an application developer requires to create their own class to handle file operations and open documents using the session method.

This protocol is detailed as follows:

#import "ARDKLib.h"
#import <Foundation/Foundation.h>

@class ARDKDocSession;

/// Information about a file being opened by the SDK
///
/// The SDK user should provide an implementation of this interface.
/// An example minimal implementation is provided in the sample app.
@protocol ARDKFileState <NSObject>

/// The path to the document to display and edit
///
/// If ARDKSecureFS is in use (i.e. documents are not being stored directly to the device
/// filesystem unencrypted, this would normally be a path that for which ARDKSecureFS_isSecure
/// will return 'true'.
///
/// If ARDKSecureFS is not in use, this should be a path to a file on the device filesystem.
@property(readonly) NSString * _Nonnull absoluteInternalPath;

/// The file type
@property(readonly) ARDKDocType docType;

/// The path which will be displayed within the UI to
/// denote the file being edited. This may be different
/// to absoluteInternalPath for two reasons.
/// The app may be supplying the path to a copy of the
/// file in absoluteInternalPath, and wish to give a
/// displayPath that better represents the location of
/// the original file. Secondly, displayPath may use
/// a more readable start of path (e.g., "Storage/")
/// in place of the true location of the file
@property(readonly) NSString * _Nonnull displayPath;

/// Whether this file can be overwritten. If YES, saving
/// back of edits to the file are not permitted, and
/// the user will need to save to another location. An
/// app might return YES here for document templates.
@property(readonly) BOOL isReadonly;

/// In some use cases, an app may supply a copy of the file
/// to be edited, which will require copying back after any
/// edits have been saved. This property keeps track of
/// whether the original file is out of date with the
/// supplied one, and hence whether copying back may be needed.
/// For apps that supply the original file directly, this
/// property can simply return NO.
@property(readonly) BOOL requiresCopyBack;

/// Information regarding the viewing state of the file (e.g.,
/// which page is being viewed).
///
/// If a FileState with a non-null viewStateInfo is passed to
/// viewControllerForSessionRestoreLastViewingState then the
/// SDK will attempt to restore the file to show the same part
/// of the document that the user was viewing when they
/// previously opened the file.
///
/// The document view will write to this before sessionDidClose is called. A class
/// implementing the ARDKFileState interface can store this
/// value (using its NSCoding interface) against the file name
/// and then arrange to restore it should the same file be
/// reopened.
@property(nullable, retain) NSObject<NSCoding> *viewingStateInfo;

/// Information method called when a session has loaded the
/// first page of the document
- (void)sessionDidLoadFirstPage:(ARDKDocSession *_Nonnull)session;

/// Information method called when the file is opened in the
/// main document view ready for viewing and editing by the user.
- (void)sessionDidShowDoc:(ARDKDocSession *_Nonnull)session;

/// Information method called when a session saves document
/// edits back to the supplied file
- (void)sessionDidSaveDoc:(ARDKDocSession *_Nonnull)session;

/// In some use cases, an app may supply a copy of the file
/// to be edited, which will require copying back after any
/// edits have been saved. This method will be called when
/// copying back may be necessary. For apps that supply the
/// original file directly, and return NO from requiresCopyBack
/// this method need do nothing.
- (void)sessionRequestedCopyBackOnCompletion:(void (^_Nonnull)(BOOL succeeded))block;

/// Information method called when a session ends. In the case
/// that an app supplies a copy of a file to be edited. This
/// method might delete the copy, since the session is no
/// longer using it. The file should NOT be copied back before
/// removal.
- (void)sessionDidClose;

@end