Coder Social home page Coder Social logo

uxmstudio / uxmpdfkit Goto Github PK

View Code? Open in Web Editor NEW
273.0 18.0 103.0 14.81 MB

An iOS PDF viewer and annotator written in Swift that can be embedded into any application.

License: MIT License

Ruby 0.59% Swift 99.41%
swift pdf-reader pdf annotator cocoapods carthage signature annotations ios

uxmpdfkit's Introduction

UXM Token Field

CI Status Version Swift Carthage Compatible License Platform

Requirements

  • iOS 9 or above
  • Xcode 8 or above
  • Swift 3.0

Note

This project is still in early stages. Right now the PDF reader works both programmatically and through interface builder. This PDF reader supports interactive forms and provides methods for overlaying text, signature and checkbox elements onto the page, as well as rendering a PDF with the elements burned back onto the PDF. See the example project for how to implement.

Installation

CocoaPods

UXMPDFKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "UXMPDFKit"

If you wish to use the Swift 2.3 version, use the following instead:

pod "UXMPDFKit", "~> 0.3.0"

Carthage

UXMPDFKit is also available through Carthage. To install just write into your Cartfile:

github "uxmstudio/UXMPDFKit"

Run carthage update to build the framework and drag the built UXMPDFKit.framework into your Xcode project.

Usage

Simple Usage

UXMPDFKit comes with a single page PDF reader with many features implemented right out of the box. Simply create a new PDFViewController, pass it a document and display it like any other view controller. It includes support for forms, a page scrubber and page scrolling.

Swift

let path = Bundle.main.path(forResource: "sample", ofType: "pdf")!
let document = try! PDFDocument(filePath: path, password: "password_if_needed")
let pdf = PDFViewController(document: document)

self.navigationController?.pushViewController(pdf, animated: true)

Objective-C

Although written in Swift, the core reader can be used in Objective-C.

NSError *error;
NSString *path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"pdf"];
PDFDocument *document = [[PDFDocument alloc] initWithFilePath:path password:@"password_if_needed" error:&error];
PDFViewController *pdfVC = [[PDFViewController alloc] initWithDocument:document];

[self.navigationController pushViewController:pdfVC animated:true];

Single Page Collection View

This collection view renders a PDF in its entirety one page at a time in photo-slideshow style.

let collectionView = PDFSinglePageViewer(frame: self.view.bounds, document: self.document)
collectionView.singlePageDelegate = self

Its delegate methods are implemented as follows:

func singlePageViewer(collectionView: PDFSinglePageViewer, didDisplayPage page: Int)
func singlePageViewer(collectionView: PDFSinglePageViewer, loadedContent content: PDFPageContentView)
func singlePageViewer(collectionView: PDFSinglePageViewer, selectedAction action: PDFAction)

Forms

User-interactable forms are supported by UXMPDFKit, but only partially. Currently only PDF's versions 1.6 & 1.7 render correctly.

Form features implemented:

  • Signatures
  • Text Fields
  • Checkboxes
  • Radio Buttons
  • Choice Boxes

Form parsing and handling is taken care of by the PDFFormViewController. It takes a document, and then is passed a PDFPageContentView to render form elements onto.

let formController = PDFFormViewController(document: self.document)
formController.showForm(contentView)

PDF rewriting is not currently supported, but flattening inputed data onto the PDF is. To render the form information onto the document, call:

func renderFormOntoPDF() -> NSURL // Returns a temporary url
func save(url: NSURL) -> Bool // Writes 

Annotations

User annotations are supported at a basic level, however instead of being written onto the PDF, are burned on at the time of saving.

Current annotation types available:

  • Pen
  • Highlighter
  • Textbox

All annotations are stored in memory until being rendered back onto the PDF by the PDFRenderer.

To create a new annotation type, you must extend the following protocol:

public protocol PDFAnnotation {

    /// The page number the annotation is located on
    var page: Int? { get set }

    /// Unique identifier to be able to select annotation by
    var uuid: String { get }

    /// Boolean representing if the annotation has been saved
    var saved: Bool { get set }

    var delegate: PDFAnnotationEvent? { get set }

    /// Force implementations to have an init
    init()

    /// A function to return a view composed of the annotations properties
    func mutableView() -> UIView

    /// Set of handlers to pass touches to annotation
    func touchStarted(_ touch: UITouch, point: CGPoint)
    func touchMoved(_ touch: UITouch, point: CGPoint)
    func touchEnded(_ touch: UITouch, point: CGPoint)

    /// Method to save annotation locally
    func save()
    func drawInContext(_ context: CGContext)

    func didEnd()

    func encode(with aCoder: NSCoder)
}

An annotation should be an object that contains its position and value, not a view. Because annotations are written onto temporary objects, they should be created, not passed by reference each time mutableView() is called.

Additionally, it is recommended that the view passed by mutableView() extend ResizableView as this allows the annotation to be moved, resized and deleted individually.

In order for annotations to be able to be listed inside of the toolbar, they must also extend PDFAnnotationButtonable.

public protocol PDFAnnotationButtonable: PDFAnnotation {

    /// Name for UIBarButtonItem representation of annotation
    static var name: String? { get }

    /// Image for UIBarButtonItem representation of annotation 
    static var buttonImage: UIImage? { get }
}

Actions

Partial action support was added in version 0.3.0 and will be increased upon in future versions.

Currently supported actions:

  • External URL
  • Go To (internal jump to page index)
  • Remote Go To
  • Named
  • Launch
  • Javascript
  • Rich Media

Tapped actions are passed to your view controller by the PDFSinglePageViewer in its contentDelegate

Renderer

In order to perform write operations back onto a PDF in an efficient format, a renderer is used. Each type of form, annotation, etc that needs to be rendered back onto the PDF should extend the following protocol:

protocol PDFRenderer {
    func render(page: Int, context:CGContext, bounds: CGRect)
}

Controllers or objects that extend this protocol can then be passed to the PDFRenderer to be written onto a temporary document or saved permanently onto the document.

let renderer = PDFRenderController(document: self.document, controllers: [
    self.annotationController,
    self.formController
])
let pdf = renderer.renderOntoPDF()

Author

Chris Anderson:

License

UXMPDFKit is available under the MIT license. See the LICENSE file for more info.

uxmpdfkit's People

Contributors

danielbyon avatar dean151 avatar dmorn avatar fhisa avatar geankozen avatar mukeshthawani avatar pushchris avatar rbresjer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uxmpdfkit's Issues

self.presentingViewController != nil

func isModal() this is returning true because self.presentingViewController isn't nil.

im presenting like in the example
self.navigationController?.pushViewController(pdf, animated: true)

Question about highlight

"Add PDF level highlighting (instead of using a pen tool, select and highlight PDF text) ".

Is this distant to an early implementation? Is that it seems extremely important to be able to generate annotations more personalized I have been working on your pod and I find it difficult to continue without this I have taken a look at your code but I am not so expert yet, in the language.

Does not save last annotation

I am using your library in one of my projects. I am unable to render all the annotations onto the pdf. Lets say I first selected pen annotation and I drew my signatures. If I then call renderOntoPDF() method, the psd won't be saved with my signatures.
Now lets say I first selected pen annotation and drew my signatures. Now I again selected text annotation and wrote some text on to the pdf. This time only signatures would be rendered on calling renderOntoPDF() method. Both the annotations won't be saved. As an extract, last annotation is not saved. This also happens with the demo project on github. Can you please help me out with this issue. I am about to launch my application. I am only left with this issue.

Here is the video:
demo.zip

Crash in PDFSinglePageViewer

Hi,

I'm trying to launch a single page PDF, and the POD crash in the PDFSinglePageViewer in cellForItemAtIndexPath at line 102.
All works fine in 0.2.4 and start failing in 0.2.5.

ERROR:
In let cell:PDFSinglePageCell = self.dequeueReusableCellWithReuseIdentifier("ContentCell", forIndexPath: indexPath) as! PDFSinglePageCell

Thanks by advance :)

Need a full example in readme

I'm a newbie in Swift and I don't know how to save the pdf file.

I use pod try UXMPDFKit to see how to save the pdf but can't see where is the code to save the pdf file.

What is the proper way to check if a PDF is password protected?

Previously, I used this piece of code to open a document and ask a password if the PDF appears to be password protected:

func openDocument() {
  do {
    document = try PDFDocument(filePath: pdfFilePath, password: password)
  } catch let err {
    switch err as? CGPDFDocumentError {
    case .some(.passwordRequired):
      askPassword(firstTime: true)
    case .some(.couldNotUnlock):
      askPassword(firstTime: false)
    default:
      break
    }
    return
  }
  
  DispatchQueue.main.async {
    self.document?.currentPage = self.page
    self.openViewer()
  }
}

However, this doesn't work anymore as the exception thrown in CGPDFDocument.swift isn't forwarded. Right now I have implemented this workaround just below the catch above, but if feels dirty:

  if document?.documentRef == nil {
    askPassword(firstTime: true)
    return
  }

What would be the proper way to check if a PDF is password-protected?

Thanks,
Rutger

Vertical Scroll?

Any plans on integrating vertical scroll? Would love it. Swiping is imo not as convinient as scrolling.

PDFViewController's showsScrubber property does not hide scrubble area on first page

let pdf = PDFViewController(document: document)
pdf.showsScrubber = false
self.navigationController?.pushViewController(pdf, animated: true)

You will notice that the very first page has an empty placeholder for the scrubble.
simulator screen shot nov 3 2016 6 53 22 pm

Scroll a few pages forward and go back to the first page, and you will notice it will look normal as expected.

Invalid use of UIColor(white:alpha:) constructor

FYI, this line in PDFPageScrubber.swift isn't correct. The range for white is 0...1.0
var thumbBackgroundColor = UIColor(white: 255, alpha: 0.7)

I get this in the console when that line is executed.

2016-11-10 12:13:17.082533 UXMPDFKit_Example[76788:10357771] [Graphics] UIColor created with component values far outside the expected range. Set a breakpoint on UIColorBreakForOutOfRangeColorComponents to debug. This message will only be logged once.

Memory issue !!!!

The memory keeps on increasing when there is a bigger pdf file and we highlight the text it eventually crashes the application.

Load pdf from remote url

<!— Provide a general summary of the issue in the Title above —>

Expected Behavior

Want to load pdf from remote url rather than from local.

Please help.

Initialization from NSData is not supported

At the moment the only initialization possible with the PDFDocument is from an URL string.

I was wondering me if there's any plan to implement a version to support initialization from NSData.

Load PDFViewcontroller in my UIViewController

I'm trying to put PDFViewController in my custom view "not PUSH VIEW"
to can add custom toolBar buttons on it.
So can you advise me how can I put this controller in my custom view?

Your Environment

<!— Include as many relevant details about the environment you experienced the bug in —>

  • iOS Version:
  • Xcode Version:
  • Swift Version:

Editable PDF forms resetting after scrolling far enough away

Basically the app we are working on has to be able to edit multiple page documents, and currently the library allows us to do this perfectly fine however after we scroll more than one page away from the first page it resets, and the filled out text boxes reset themselves. The pen annotations stay, but we need the editable elements native to the PDF to stay intact as well. Is there any parameter we can change to increase the memory so the edited page stays? Thanks in advance

Sometimes annotations fail to display

  1. Bring up a PDFViewController and display it (tap on the 'Show Full PDF Viewer' in the example project)
  2. Move the PDF page slightly but not enough to turn the page
  3. Tap on the annotations button, and the pen button
  4. Try to annotate the page

Issues with undoing annotations

Seems the there is some weirdness with undoing annotations.

Using the example program built to an iPad Air 2:

Add annotation 1 (Text)
Add annotation 2 (Line)
Add annotation 3 (Highlight)
Click undo (both annotations 2 and 3 are undone)
Click "Back"
Click "Show Full PDF Viewer" (annotations 1 and 3 are visible?)

Can someone look into this...

  • The actual annotation types don't seem to matter, it more an order of operations issue.

Zoom on double tap

Thanks for taking your time to make this. I have a question i would like to ask.

I am using the single page collectionview to display a PDF, and i can zoom in on the content with pinching. Is it possible to zoom in with simply doubletapping on the collectionview?

If not, is it possible to add this function manually? Im new to programming and i've been trying to google this, without results.

Thanks in advance!

Parly editable PDF

There are some PDFs on which it's only possible to write on parts of the PDF and not the whole page. There are only some PDFs where this behaviour appears.

  • iOS Version: 10.0
  • Xcode Version: 8.3.3
  • Swift Version: 3

Issues with rotation

When rotating in horizontal paged mode PDF's become incorrect size. Depending on zoom level when rotating PDF might either become too small for page, or too large and not be able to be zoomed out.

Toggle visibility of individual annotations for PDFViewController

<!— Provide a general summary of the issue in the Title above —>
I want to restrict the highlight and text annotations inside the PDFViewController while allowing the pen annotation.

Expected Behaviour

Add boolean values to controller the buttons for each annotation inside PDFViewController. i.e. instead of having a catch-all allowsAnnotations, have

  • allowHighlighterAnnotation
  • allowPenAnnotation
  • allowTextAnnotation

These booleans would be used inside the function fileprivate func rightBarButtons() so that the buttons would not be appended in the navigation.

Current Behaviour

A single boolean value for allowsAnnotations for the PDFViewController

UICollectionViewFlowLayout is not defined

The behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
The relevant UICollectionViewFlowLayout instance is UICollectionViewFlowLayout:, and it is attached to <UXMPDFKit.PDFSinglePageViewer:;
Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

Any idea if its somthing on my end?

Add ability to set a custom action on the share form bar button item

It might be nice to add the ability to set a custom action to trigger when the share form bar button is tapped, instead of always bringing up the UIActivityViewController.

This might be accomplished by defining an action style enum on PDFViewController, something to the effect of:

/// Action button style
public enum ActionStyle {
    /// Brings up an activity sheet to share or open PDF in another app
    case activitySheet
        
    /// Performs a custom action
    case customAction((Void) -> ())
}

UICollectionViewFlowLayout - Behavior not defined

Hi,

I am seeing this when the device is in landscape or portrait

The behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
The relevant UICollectionViewFlowLayout instance is <UICollectionViewFlowLayout: 0x101544c00>, and it is attached to <UXMPDFKit.PDFSinglePageViewer: 0x10208d000; baseClass = UICollectionView; frame = (0 0; 1024 704); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x170054550>; layer = <CALayer: 0x17002d5a0>; contentOffset: {0, 0}; contentSize: {2048, 768}> collection view layout: <UICollectionViewFlowLayout: 0x101544c00>.
Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

Just wondering what could possibly be causing this?

Carthage build Error

Hi,

I've the following error building from Carthage:
Dependency "UXMPDFKit" has no shared framework schemes for any of the platforms: iOS

Thank you in advance,
Omar.

UXMPDFKit is not rendering the all the Graphics

UXMPDFKit is not rendering the all the Graphics involved in the pdf file, attached the sample pdf file which I was using to test different size and graphics in it.

Expected Behavior

It should render all contents including the graphics like images

Current Behavior

is not rendering the all the Graphics involved in the pdf file
Attached screenshot and original pdf which was used for testing

sample_pdf_diff_size.pdf
screen shot 2017-09-19 at 8 59 09 pm
screen shot 2017-09-19 at 8 59 12 pm

PDFDocument object conflicts with PDFKit.PDFDocument

When I embed UXMPDFKit into my project, even without importing the framework in a particulat file, PDFDocument object inside library cause Xcode fails to import new PDFKit.PDFDocument and mark it as unavailable. I suggest renaming it to UXMPDFDocument to avoid ambiguity.

Your Environment

  • iOS Version: 11.0
  • Xcode Version: 9.0
  • Swift Version: 4.0

Examples: Signature + Annotation

Hi,

This is a really nice project, it would be great if you please include examples for adding Signature and Annotations.

Thanks

Couple code issues

  1. I noticed that didFinishLaunchingWithOptions is never called in the app delegate in the Example app. The prototype has changed. App Path never appears. This is with Xcode 8.1

  2. This line in PDFFormField.swift always fails with the Sample2.pdf file.

     if let flagsObj = dict["Ff"] as? UInt {
    

The type of the "Ff" field is some kind of pointer that doesn't cast to UInt. Consequently radio buttons are never detected.

Rendering to PDF

I am trying to use the example to extend the protocol and render onto a pdf but it isn't working.

When I use the following code

let renderer = PDFRenderController(document: self.document, controllers: [
    self.annotationController,
    self.formController
])
let pdf = renderer.renderOntoPDF()

I get an error that the PDFRenderController initializer is inaccessible due to the internal protection level.

Memory Leak Issue!

screen shot 2017-02-09 at 1 49 03 pm
I found there is huge memory leak in this library, When i tried to profile the issue the almost all (78 percent of memory id used by library and the leak tool points to following line as suspect . please Have a look once. Hope will be in good condition soon, waiting for issue be closed .

let thumbRender = PDFSnapshotRenderer(snapshot: thumbnail)
       thumbRender.completionBlock = {
           self.rendersInProgress.removeValue(forKey: guid)
           DispatchQueue.main.async {
               self.progressBlock?(thumbRender.snapshot)
               completion?(thumbRender.snapshot)
           }

Crash when opening Full PDF Viewer in Example Project

Hi! I've just build and run your Example Program with Xcode 8.0. It's OK for the first time after I click 'Show Full PDF Viewer', but the program crashed in a second when I back to ExampleViewController and click it again. The problem wasn't gone until I deleted the program in Simulator. And the problem comes again after I run the Example and click 'Show Full PDF Viewer'. Can you help to have a look please?
Very thanks!

'annotations = aDecoder.decodeObject(forKey: "annotations") as! [PDFAnnotation]' in PDFAnnotationStore

Undo Button Functionality?

is the undo button supposed to work with the pen annotation? If not is this a planned feature and could it be implemented sometime soon?

PDF with background and text does not render right

I receive PDF from my local gas billing company. It renders fine when I open with the Mail client pdf viewer. But when I open with UXM based custom app, one that I wrote, it shows only the image, not the text.

I cannot upload the PDF to this issue since it has my contact details on it. But if you want it to be shared in private, let me know.

Crash when passing nil as a password on PDFDocument creation

Hi and first of all thanks for the work!

I encountered an issue while using the library : when I tried to create a PDFDocument instance for a file without a password, my first attempt was to call PDFDocument(filePath: path, password: nil), which caused my app to crash with mysterious error messages.

I managed to fixed it by calling PDFDocument(filePath: path, password: "").

This should be either stated clearly in the docs (maybe I've missed it?) or fixed in the code.

Cheers!

Copy pdf text?

Hi, I have a pdf text, how to copy text?

  • iOS Version: 9/10
  • Xcode Version: 8.2
  • Swift Version: 3.0

Extending the annotations

Hi,

I am trying to extend the annotations with one of my own. However, to do this i need to subclass pdfviewcontroller and annotationcontroller and point to the new annotationcontroller in the new pdfviewcontroller. This is not possible because of access levels:

lazy var annotationController: PDFAnnotationController = PDFAnnotationController(document: self.document, delegate: self)

both document and annotationController have access level internal. Do i need to find a new route or am i doing something wrong here? It's my first time coding for ios, so it could well be :)

Thanks for your time

PDFViewController - currentPage does not update

When scrolling from page to page, the currentPage property does not get updated.

Expected Behavior

currentPage is updated to the current page

Current Behavior

currentPage is always equal to 1, if the scrubber is not used

Steps to Reproduce (for bugs)

<!— Provide a set of steps to reproduce this bug. Include code if relevant —>

  1. open a document
  2. scroll to the second page
  3. click on the document if the hub is not visible
  4. Check page number (1 of n) instead of (2 of n)

Your Environment

<!— Include as many relevant details about the environment you experienced the bug in —>

  • iOS Version: 10.2.1
  • Xcode Version: 8.3.2
  • Swift Version: 3

Checkmarks Could Be Improved

Couple suggestions for the checkboxes. Currently the checkboxes are invisible when not checked and even when checked they don't really look like checkboxes.

What I suggest is to configure the buttons as toggle buttons. You'll need two images, one for the checked appearance and the other for the unchecked appearance. Set the checked image for the selected state and the unchecked image for the normal state. Add an action method for touchupinside and button.selected = !button.selected. When the selected state is set the checkmark image will appear.

If you felt like it you can easily make a UIButton subclass with that behavior built in and just use that when you're building the checkmark button. This is probably best.

Open viewer at specific page

Hi Chris,

First of all: great work! Thanks for this great PDF viewer.

If I set the PDFDocument to a specific page before initializing the PDFViewController with it, the page scrubber is shown at the correct page, but the document viewer isn't:

let document = PDFDocument(filePath: pdfFilePath)
document.currentPage = 33
let pdfVc = PDFViewController(document: document)

Is this an easy fix?

Best regards,
Rutger

Choose color

Do you plan to add a color picker? Right now this works with hardcoded colors.

Saving PDF Form for re-editing

It is a very much required feature

Expected Behavior

Save filled in form values into original PDF

Current Behavior

generating static PDF which is no longer editable

Changing colour ?

Hello, Thanks for this great library !
I have a question about colours, is it possible to change it (pen or/and text) ?
I would like doing a "undo" programmatically as well (I have a custom view to choose between different actions).
I don't want to change your code to keep this repository up-to-date in my project.
Thanks !

  • iOS Version: 10.2.1
  • Xcode Version: 8.3.3
  • Swift Version: 3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.