XFDF Support
XFDF is an XML-like standard from Adobe XFDF for encoding annotations and forms (see this XFDF overview). It is compatible with Adobe Acrobat and several other third-party frameworks.
ℹ️ Note: XFDF has various limitations. In most cases, using PSPDFKit Instant will result in a smaller file and better synchronization.
PSPDFKit for iOS supports both reading and writing XFDF. It also offers an annotation provider subclass — PSPDFXFDFAnnotationProvider
— that will save/load annotations to/from XFDF automatically.
Parsing XFDF
To read from an XFDF file:
1 2 3 4 5 6 7 8 9 | // Load from an example XFDF file. let externalAnnotationsFile = URL(fileURLWithPath: "path/to/XFDF.xfdf") // Create `document` and set up the XFDF provider. let document = PSPDFDocument() document.didCreateDocumentProviderBlock = {(_ documentProvider: PSPDFDocumentProvider) -> Void in let XFDFProvider = PSPDFXFDFAnnotationProvider(documentProvider: documentProvider, fileURL: externalAnnotationsFile) documentProvider.annotationManager.annotationProviders = [XFDFProvider] } |
1 2 3 4 5 6 7 8 9 | // Load from an example XFDF file. NSURL *externalAnnotationsFile = [NSURL fileURLWithPath:[docsFolder stringByAppendingPathComponent:@"XFDFTest.xfdf"]]; // Create `document` and set up the XFDF provider. PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL]; document.didCreateDocumentProviderBlock = ^(PSPDFDocumentProvider *documentProvider) { PSPDFXFDFAnnotationProvider *XFDFProvider = [[PSPDFXFDFAnnotationProvider alloc] initWithDocumentProvider:documentProvider fileURL:externalAnnotationsFile]; documentProvider.annotationManager.annotationProviders = @[XFDFProvider]; }; |
Exporting to XFDF
You can export annotations and form fields from a document to an XFDF file like so:
1 2 3 4 5 6 7 8 9 10 | // Collect all existing annotations from the document. let annotations = document.allAnnotations(of: .all).values.flatMap { $0 } // Write the file. let dataSink = try! PSPDFFileDataSink(fileURL: externalAnnotationsFile) do { try PSPDFXFDFWriter().write(annotations, to: dataSink, documentProvider: document.documentProviders.first!) } catch { print("Failed to write XFDF file: \(error.localizedDescription))") } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Collect all existing annotations from the document. NSMutableArray<PSPDFAnnotation *> *annotations = [NSMutableArray<PSPDFAnnotation *> array]; for (NSArray<PSPDFAnnotation *> *pageAnnotations in [document allAnnotationsOfType:PSPDFAnnotationTypeAll].allValues) { [annotations addObjectsFromArray:pageAnnotations]; } // Write the file. NSError *error; PSPDFFileDataSink *dataSink = [[PSPDFFileDataSink alloc] initWithFileURL:externalAnnotationsFile options:PSPDFDataSinkOptionNone error:&error]; NSAssert(dataSink != nil, @"%@", error); if (![[PSPDFXFDFWriter new] writeAnnotations:annotations toDataSink:dataSink documentProvider:tempDocument.documentProviders[0] error:&error]) { NSLog(@"Failed to write XFDF file: %@", error.localizedDescription); } |
Handling External Changes
If the XFDF file used to store annotations for a document is changed outside of PSPDFKit, the cache for that document needs to be manually cleared. For performance reasons, PSPDFCache
does not take the annotations on a given page into account. As such, when a previously used document is loaded in a PSPDFViewController
with an XFDF file that was changed externally, the cache will return stale images.
To counter this, you can clear the cache like so:
1 2 | // Where `document` is a PSPDFDocument instance. PSPDFKit.sharedInstance.cache.remove(for: document) |
1 2 | // Where `document` is a PSPDFDocument instance. [PSPDFKit.sharedInstance.cache removeCacheForDocument:document]; |