{"id":35152365,"url":"https://github.com/uxmstudio/uxmpdfkit","last_synced_at":"2025-12-28T16:03:53.473Z","repository":{"id":40614237,"uuid":"58053403","full_name":"uxmstudio/UXMPDFKit","owner":"uxmstudio","description":"An iOS PDF viewer and annotator written in Swift that can be embedded into any application.","archived":false,"fork":false,"pushed_at":"2020-12-21T05:10:17.000Z","size":15165,"stargazers_count":274,"open_issues_count":42,"forks_count":104,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-09-18T21:27:54.110Z","etag":null,"topics":["annotations","annotator","carthage","cocoapods","ios","pdf","pdf-reader","signature","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uxmstudio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-04T13:16:43.000Z","updated_at":"2025-08-27T14:08:46.000Z","dependencies_parsed_at":"2022-08-21T06:20:16.934Z","dependency_job_id":null,"html_url":"https://github.com/uxmstudio/UXMPDFKit","commit_stats":null,"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"purl":"pkg:github/uxmstudio/UXMPDFKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uxmstudio%2FUXMPDFKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uxmstudio%2FUXMPDFKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uxmstudio%2FUXMPDFKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uxmstudio%2FUXMPDFKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uxmstudio","download_url":"https://codeload.github.com/uxmstudio/UXMPDFKit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uxmstudio%2FUXMPDFKit/sbom","scorecard":{"id":913761,"data":{"date":"2025-08-11","repo":{"name":"github.com/uxmstudio/UXMPDFKit","commit":"8dbfdbd8c865390a49f9de97c96bd2a82aa16f4d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Code-Review","score":2,"reason":"Found 5/17 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 18 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T20:13:10.978Z","repository_id":40614237,"created_at":"2025-08-24T20:13:10.978Z","updated_at":"2025-08-24T20:13:10.978Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28101403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-28T02:00:05.685Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotations","annotator","carthage","cocoapods","ios","pdf","pdf-reader","signature","swift"],"created_at":"2025-12-28T16:00:39.764Z","updated_at":"2025-12-28T16:03:53.466Z","avatar_url":"https://github.com/uxmstudio.png","language":"Swift","readme":"![UXM Token Field](https://uxmstudio.com/public/images/uxmpdfkit.png)\n\n[![CI Status](http://img.shields.io/travis/uxmstudio/UXMPDFKit.svg?style=flat)](https://travis-ci.org/uxmstudio/UXMPDFKit)\n[![Version](https://img.shields.io/cocoapods/v/UXMPDFKit.svg?style=flat)](http://cocoapods.org/pods/UXMPDFKit)\n![Swift](https://img.shields.io/badge/%20in-swift%203.0-orange.svg)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![License](https://img.shields.io/cocoapods/l/UXMPDFKit.svg?style=flat)](http://cocoapods.org/pods/UXMPDFKit)\n[![Platform](https://img.shields.io/cocoapods/p/UXMPDFKit.svg?style=flat)](http://cocoapods.org/pods/UXMPDFKit)\n\n## Requirements\n- iOS 9 or above\n- Xcode 8 or above\n- Swift 3.0\n\n## Note\n\nThis 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.\n\n## Installation\n\n### CocoaPods\n\nUXMPDFKit is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod \"UXMPDFKit\"\n```\n\nIf you wish to use the Swift 2.3 version, use the following instead:\n```ruby\npod \"UXMPDFKit\", \"~\u003e 0.3.0\"\n```\n\n### Carthage\n\nUXMPDFKit is also available through [Carthage](https://github.com/Carthage/Carthage).\nTo install just write into your Cartfile:\n\n```ogdl\ngithub \"uxmstudio/UXMPDFKit\"\n```\n\nRun `carthage update` to build the framework and drag the built `UXMPDFKit.framework` into your Xcode project.\n\n## Usage\n### Simple Usage\nUXMPDFKit 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.\n#### Swift\n```swift\nlet path = Bundle.main.path(forResource: \"sample\", ofType: \"pdf\")!\nlet document = try! PDFDocument(filePath: path, password: \"password_if_needed\")\nlet pdf = PDFViewController(document: document)\n\nself.navigationController?.pushViewController(pdf, animated: true)\n```\n\n#### Objective-C\nAlthough written in Swift, the core reader can be used in Objective-C.\n```objective-c\nNSError *error;\nNSString *path = [[NSBundle mainBundle] pathForResource:@\"sample\" ofType:@\"pdf\"];\nPDFDocument *document = [[PDFDocument alloc] initWithFilePath:path password:@\"password_if_needed\" error:\u0026error];\nPDFViewController *pdfVC = [[PDFViewController alloc] initWithDocument:document];\n\n[self.navigationController pushViewController:pdfVC animated:true];\n```\n\n### Single Page Collection View\nThis collection view renders a PDF in its entirety one page at a time in photo-slideshow style. \n```swift\nlet collectionView = PDFSinglePageViewer(frame: self.view.bounds, document: self.document)\ncollectionView.singlePageDelegate = self\n```\n\nIts delegate methods are implemented as follows:\n\n```swift\nfunc singlePageViewer(collectionView: PDFSinglePageViewer, didDisplayPage page: Int)\nfunc singlePageViewer(collectionView: PDFSinglePageViewer, loadedContent content: PDFPageContentView)\nfunc singlePageViewer(collectionView: PDFSinglePageViewer, selectedAction action: PDFAction)\n```\n\n\n### Forms\nUser-interactable forms are supported by UXMPDFKit, but only partially. Currently only PDF's versions 1.6 \u0026 1.7 render correctly.\n\nForm features implemented:\n- [x] Signatures\n- [x] Text Fields\n- [x] Checkboxes\n- [ ] Radio Buttons\n- [ ] Choice Boxes\n\nForm 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.\n```swift\nlet formController = PDFFormViewController(document: self.document)\nformController.showForm(contentView)\n```\n\nPDF rewriting is not currently supported, but flattening inputed data onto the PDF is. To render the form information onto the document, call:\n```swift\nfunc renderFormOntoPDF() -\u003e NSURL // Returns a temporary url\nfunc save(url: NSURL) -\u003e Bool // Writes \n```\n\n\n### Annotations\nUser annotations are supported at a basic level, however instead of being written onto the PDF, are burned on at the time of saving. \n\nCurrent annotation types available: \n* Pen\n* Highlighter\n* Textbox\n\nAll annotations are stored in memory until being rendered back onto the PDF by the PDFRenderer.\n\nTo create a new annotation type, you must extend the following protocol:\n\n```swift\npublic protocol PDFAnnotation {\n\n    /// The page number the annotation is located on\n    var page: Int? { get set }\n\n    /// Unique identifier to be able to select annotation by\n    var uuid: String { get }\n\n    /// Boolean representing if the annotation has been saved\n    var saved: Bool { get set }\n\n    var delegate: PDFAnnotationEvent? { get set }\n\n    /// Force implementations to have an init\n    init()\n\n    /// A function to return a view composed of the annotations properties\n    func mutableView() -\u003e UIView\n\n    /// Set of handlers to pass touches to annotation\n    func touchStarted(_ touch: UITouch, point: CGPoint)\n    func touchMoved(_ touch: UITouch, point: CGPoint)\n    func touchEnded(_ touch: UITouch, point: CGPoint)\n\n    /// Method to save annotation locally\n    func save()\n    func drawInContext(_ context: CGContext)\n\n    func didEnd()\n\n    func encode(with aCoder: NSCoder)\n}\n```\n\nAn 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. \n\nAdditionally, it is recommended that the view passed by ```mutableView()``` extend ```ResizableView``` as this allows the annotation to be moved, resized and deleted individually.\n\nIn order for annotations to be able to be listed inside of the toolbar, they must also extend ```PDFAnnotationButtonable```.\n\n```swift\npublic protocol PDFAnnotationButtonable: PDFAnnotation {\n\n    /// Name for UIBarButtonItem representation of annotation\n    static var name: String? { get }\n\n    /// Image for UIBarButtonItem representation of annotation \n    static var buttonImage: UIImage? { get }\n}\n```\n\n### Actions\n\nPartial action support was added in version 0.3.0 and will be increased upon in future versions.\n\nCurrently supported actions:\n- [x] External URL\n- [x] Go To (internal jump to page index)\n- [ ] Remote Go To\n- [ ] Named\n- [ ] Launch\n- [ ] Javascript\n- [ ] Rich Media\n\nTapped actions are passed to your view controller by the PDFSinglePageViewer in its ```contentDelegate```\n\n### Renderer \nIn 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:\n\n```swift\nprotocol PDFRenderer {\n    func render(page: Int, context:CGContext, bounds: CGRect)\n}\n```\n\nControllers 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.\n\n```swift\nlet renderer = PDFRenderController(document: self.document, controllers: [\n    self.annotationController,\n    self.formController\n])\nlet pdf = renderer.renderOntoPDF()\n```\n\n\n# Author\nChris Anderson:\n- chris@uxmstudio.com\n- [Home Page](http://uxmstudio.com)\n\n# License\n\nUXMPDFKit is available under the MIT license. See the LICENSE file for more info.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuxmstudio%2Fuxmpdfkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuxmstudio%2Fuxmpdfkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuxmstudio%2Fuxmpdfkit/lists"}