Skip to content

Instantly share code, notes, and snippets.

@aheze
Last active April 11, 2022 11:09
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aheze/dbc7f9b452e4f86f2d8fe278b3c5001f to your computer and use it in GitHub Desktop.
Save aheze/dbc7f9b452e4f86f2d8fe278b3c5001f to your computer and use it in GitHub Desktop.
UIDocumentPickerViewController example in Swift 5. Bug fixed version of this article: https://medium.com/flawless-app-stories/a-swifty-way-to-pick-documents-59cad1988a8a
//
// DocumentPicker.swift
import UIKit
import MobileCoreServices
protocol DocumentDelegate: class {
func didPickDocument(document: Document?)
}
class Document: UIDocument {
var data: Data?
override func contents(forType typeName: String) throws -> Any {
guard let data = data else { return Data() }
return try NSKeyedArchiver.archivedData(withRootObject:data,
requiringSecureCoding: true)
}
override func load(fromContents contents: Any, ofType typeName:
String?) throws {
guard let data = contents as? Data else { return }
self.data = data
}
}
open class DocumentPicker: NSObject {
private var pickerController: UIDocumentPickerViewController?
private weak var presentationController: UIViewController?
private weak var delegate: DocumentDelegate?
private var pickedDocument: Document?
init(presentationController: UIViewController, delegate: DocumentDelegate) {
super.init()
self.presentationController = presentationController
self.delegate = delegate
}
public func displayPicker() {
/// pick movies and images
self.pickerController = UIDocumentPickerViewController(documentTypes: [kUTTypeMovie as String, kUTTypeImage as String], in: .import)
self.pickerController!.delegate = self
self.presentationController?.present(self.pickerController!, animated: true)
}
}
extension DocumentPicker: UIDocumentPickerDelegate {
/// delegate method, when the user selects a file
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else {
return
}
documentFromURL(pickedURL: url)
delegate?.didPickDocument(document: pickedDocument)
}
/// delegate method, when the user cancels
public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
delegate?.didPickDocument(document: nil)
}
private func documentFromURL(pickedURL: URL) {
/// start accessing the resource
let shouldStopAccessing = pickedURL.startAccessingSecurityScopedResource()
defer {
if shouldStopAccessing {
pickedURL.stopAccessingSecurityScopedResource()
}
}
NSFileCoordinator().coordinate(readingItemAt: pickedURL, error: NSErrorPointer.none) { (readURL) in
let document = Document(fileURL: readURL)
pickedDocument = document
}
}
}
//
// ViewController.swift
class ViewController: UIViewController, DocumentDelegate {
override func viewDidLoad() {
super.viewDidLoad()
/// set up the document picker
documentPicker = DocumentPicker(presentationController: self, delegate: self)
}
/// callback from the document picker
func didPickDocument(document: Document?) {
if let pickedDoc = document {
let fileURL = pickedDoc.fileURL
/// do what you want with the file URL
}
}
}
@mrfarukturgut
Copy link

Thanks for sharing. However data in Document always returns nil. Can you share a fix for that?

@aheze
Copy link
Author

aheze commented Nov 21, 2020

Hmm...

This works for me:

func didPickDocument(document: Document?) {
    if let pickedDoc = document {
        let fileURL = pickedDoc.fileURL
        let data = try Data(contentsOf: fileURL)
    }
}

@BrahmamM
Copy link

BrahmamM commented Apr 11, 2022

Usage.swift


      import UIKit
      import MobileCoreServices

   class ViewController: UIViewController, DocumentDelegate {
       override func viewDidLoad() {
         super.viewDidLoad()
    }

     @IBAction func actionButtonTapped(_ sender: Any) {
        let documentPicker = DocumentPicker(presentationController: self, delegate: self)
       documentPicker.displayPicker()
     }
  
/// callback from the document picker
func didPickDocument(document: Document?) {
    if let pickedDoc = document {
        let fileURL = pickedDoc.fileURL
        /// do what you want with the file URL
        print(fileURL)
        let data = try Data(contentsOf: fileURL)
    }
   }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment