Document Picker View Controller issue in Swift - ios

I have a button in my view controller, when click a button it open a document picker view controller, i have set type like KUTypePDF and KUTypeZipArchive , when i select any of these item from google drive the picker controller gets dismiss and in console it shows a long un finished strings of number that doesn't stop. I'm confused why it is showing that long string. What i want is that after i select any file from google drive it should be shown in my app. I'm getting the file url right. My code is this,
#IBAction func docsBtnTapped(_ sender: Any) {
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF),String(kUTTypeZipArchive)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .fullScreen
self.present(importMenu, animated: true, completion: nil)}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
let cico = url as URL
print("The Url is : /(cico)", cico)
do {
let weatherData = try NSData(contentsOf: cico, options: NSData.ReadingOptions())
print(weatherData)
let activityItems = [weatherData]
let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
if UI_USER_INTERFACE_IDIOM() == .phone {
self.present (activityController, animated: true, completion: {
print("Hello")
})
}
else {
let popup = UIPopoverController(contentViewController: activityController)
popup.present(from: CGRect(x: CGFloat(self.view.frame.size.width / 2), y: CGFloat(self.view.frame.size.height / 4), width: CGFloat(0), height: CGFloat(0)), in: self.view, permittedArrowDirections: .any, animated: true)
}
} catch {
print(error)
}
//optional, case PDF -> render
//displayPDFweb.loadRequest(NSURLRequest(url: cico) as URLRequest)
}
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print(" cancelled by user")
dismiss(animated: true, completion: nil)
}
This long string come in console when i select any item of PDF or Zip file,

You can use UIDocumentInteractionController to open any kind preview from url:
Here is Simple code to open url:
var documentController:UIDocumentInteractionController!
#IBAction func btnOpenClicked(_ sender: Any) {
if let fileURL = Bundle.main.url(forResource: "icon", withExtension: "jpg") {
// Instantiate the interaction controller
self.documentController = UIDocumentInteractionController.init(url: fileURL)
self.documentController.delegate = self
self.documentController.presentPreview(animated: true)
}
else {
print("File missing! Button has been disabled")
}
}
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self
}

Related

How can I get pdf file of ibook in my application?

I want to open document file using swift 4. My requirement is that I want to use document picker. Using Document picker I can upload that file using my application.
In short in my app iIwant other documents like .pdf from device. i had try this .
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
let myURL = urls
print("import result : \(myURL)")
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print("view was cancelled")
dismiss(animated: true, completion: nil)
}
#IBAction func dsds(_ sender: Any) {
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}

share PDF file with UIActivityViewController

I am trying to share a PDF file using UIActivityViewController but when I press the button I do not have options to share the file
How can I show these options ?
![](https://i.stack.imgur.com/ywDQw.jpg
import UIKit
import PDFKit
import MessageUI
import UIKit.UIGestureRecognizerSubclass
class BookViewController: UIViewController, UIPopoverPresentationControllerDelegate, PDFViewDelegate, ActionMenuViewControllerDelegate, OutlineViewControllerDelegate, MFMailComposeViewControllerDelegate {
#IBOutlet weak var btn: UIButton!
var pdfDocument: PDFDocument?
#IBOutlet weak var pdfView: PDFView!
#IBOutlet weak var webview: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
pdfView.autoScales = true
pdfView.displayMode = .singlePage
pdfView.displayDirection = .horizontal
pdfView.usePageViewController(true, withViewOptions: [UIPageViewControllerOptionInterPageSpacingKey: 20])
pdfView.document = pdfDocument
resume()
// ActivityViewController
}
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: { (context) in
}, completion: nil)
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
func actionMenuViewControllergmailDocument(_ actionMenuViewController: ActionMenuViewController) {
}
func actionMenuViewControllerShareDocument(_ actionMenuViewController: ActionMenuViewController) {
}
func actionMenuViewControllerPrintDocument(_ actionMenuViewController: ActionMenuViewController) {
}
func outlineViewController(_ outlineViewController: OutlineViewController, didSelectOutlineAt destination: PDFDestination) {
resume()
pdfView.go(to: destination)
}
private func resume() {
let backButton = UIBarButtonItem(image: #imageLiteral(resourceName: "Chevron"), style: .plain, target: self, action: #selector(back(_:)))
let actionButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(showActionMenu(_:)))
navigationItem.leftBarButtonItems = [backButton, actionButton]
pdfView.isHidden = false
}
#objc func resume(_ sender: UIBarButtonItem) {
resume()
}
#objc func back(_ sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}
#objc func showActionMenu(_ sender: UIBarButtonItem) {
if let viewController = storyboard?.instantiateViewController(withIdentifier: String(describing: ActionMenuViewController.self)) as? ActionMenuViewController {
let activityVC = UIActivityViewController(activityItems: [self.pdfDocument!], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view
self.present(activityVC, animated: true, completion: nil)
}
}
}
In SWIFT 4
#IBAction func sharePDF(_ sender: : Any) {
let fm = FileManager.default
var pdfURL = (fm.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
pdfURL = pdfURL.appendingPathComponent("GridLines.pdf") as URL
//Rename document name to "Hello.pdf"
let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Hello.pdf") as NSURL
do {
let data = try Data(contentsOf: pdfURL)
try data.write(to: url as URL)
let activitycontroller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
if activitycontroller.responds(to: #selector(getter: activitycontroller.completionWithItemsHandler))
{
activitycontroller.completionWithItemsHandler = {(type, isCompleted, items, error) in
if isCompleted
{
print("completed")
}
}
}
activitycontroller.excludedActivityTypes = [UIActivityType.airDrop]
activitycontroller.popoverPresentationController?.sourceView = self.view
self.present(activitycontroller, animated: true, completion: nil)
}
catch {
//ERROR
}
}
You can also share the PDF data itself using the dataRepresentation() function
guard let data = document?.dataRepresentation() else { return }
let activityController = UIActivityViewController(activityItems: [data], applicationActivities: nil)
present(activityController, animated: true)
Cheers
Try like this
let fileManager = FileManager.default
let docsurl = try! fileManager.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let documentoPath = docsurl.appendingPathComponent("yourfile.pdf")
if fileManager.fileExists(atPath: documentoPath){
let pdfData = NSData(contentsOfFile: documentoPath)
var activityViewController = UIActivityViewController(activityItems: ["Your title that you wanna share", pdfData], applicationActivities: nil) // and present it
present(activityViewController, animated: true) {() -> Void in }
}
Its working fine ... I use it .
You already have a PDFDocument object, so reconstructing the file url is unnecessary. Simply pass your PDFDocument's documentURL property instead:
let activityVC = UIActivityViewController(activityItems: [self.pdfDocument!.documentURL!], applicationActivities: nil)
Try with this
let fileManager = FileManager.default
let docsurl = try! fileManager.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let documentoPath = docsurl.appendingPathComponent("documento.pdf")
if fileManager.fileExists(atPath: documentoPath){
let documento = NSData(contentsOfFile: documentoPath)
let activityViewController: UIActivityViewController =
UIActivityViewController(activityItems: [documento!],
applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView=self.view
present(activityViewController, animated: true, completion: nil)
}
else {
print("document was not found")
}
Call this method on button click
func sharePdf() {
let activityViewController = UIActivityViewController(activityItems: [pdfView.document!.dataRepresentation()!], applicationActivities: nil)
present(activityViewController, animated: true)
}
For sharing image just change the activity item
func shareImg() {
let activityViewController = UIActivityViewController(activityItems: [imageView.image!], applicationActivities: nil)
present(activityViewController, animated: true)
}
You can share multiple items at once, by adding it in activityItems array

How do I do Custom Alert Action Sheet?

I have a mail API which sends some information and document. I send only Files documents but I want to show one more choice in UIDocumentPickerView.
How can I show the list " document , photos , camera etc." in the same picker with images ?
My code is :
#available(iOS 8.0, *)
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
let urlData = url as URL
let theFile = urlData.absoluteString
self.documentName.text = "\(theFileName)"
}
#available(iOS 8.0, *)
public func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
dismiss(animated: true, completion: nil)
}
func mySpecialFunction(){
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
It's a custom component, you need to code it yourself of find something similar on GitHub or CocoaControls.

Swift 3 taking picture and saving

Working in Swift 3. I found numerous questions with answers and then also blogs, yet everything I've tried didn't work. I am just trying to capture a camera shot I take and save it to the documents. But it isn't being saved as it doesn't show up under devices documents when viewed from within xcode and I don't get any errors or similar. I'm at a bit of a lost here.
Code that have for getting the image and saving it
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var pickedImage = UIImage()
pickedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
picker.dismiss(animated: true, completion: nil)
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMddHHmmss"
let fileNameWithExtension = "ts_\(formatter.string(from: currentDateTime)).png"
//create path
let imagePath = fileInDocumentsDirectory(filename: fileNameWithExtension)
imageStringPathSet = fileNameWithExtension
imageSet = pickedImage
if saveImage(image: pickedImage, path: imagePath) {
cameraButton.setImage(#imageLiteral(resourceName: "ic_camerashot_yes60dp"), for: UIControlState.normal)
return
}
cameraButton.setImage(#imageLiteral(resourceName: "ic_camerashot_no60dp"), for: UIControlState.normal)
}
func fileInDocumentsDirectory(filename: String)-> URL {
return try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(filename)
}
func saveImage(image: UIImage, path: URL) -> Bool {
print(path)
guard let pngImageData = UIImagePNGRepresentation(image) else {
print("error")
return false
}
var resultValid = false
do {
let results = try pngImageData.write(to: path, options: [.atomicWrite])
print(results) //prints ()
resultValid = true
}
catch {
resultValid = false
print(error)
}
return resultValid
}
When I print the path it prints
file:///var/mobile/Containers/Data/Application/01EB6A70-34C6-4481-BE5B-7F7AB5E6703F/Documents/ts_20161221145652.png
Which I believe is correct. If everything works correctly, it changes an image on the screen yet it never changes and the imageStringPathSet isn't set either which is a class variable. Anyone have any ideas on what I need to do to get this to work?
Solution
Turns out the cause was that I was resetting everything in the view in viewWillAppear. Once I fixed this, things worked fine. Thanks everyone for your feedback. Hope this helps someone else to not do what I did.
As per the request in the comments, here's my code that (a) uses the UIImagePickerController to either select from the camera roll, then (b) uses the UIActivityViewController to let the user choose among several possible ways to save/attach the image to several sources of output.
While this isn't saving to the document directory, it may be a better route to go. Please pay attention to a few notes after the code listing.
My "select" view controller, which allows a user to either pick from the camera roll or take a picture:
extension SelectViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// MARK: Camera App
func openCameraApp() {
if UIImagePickerController.availableCaptureModes(for: .rear) != nil {
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = .photo
picker.modalPresentationStyle = .fullScreen
present(picker,
animated: true,
completion: nil)
} else {
noCamera()
}
}
func noCamera(){
let alertVC = UIAlertController(
title: "No Camera",
message: "Sorry, this device has no camera",
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style:.default,
handler: nil)
alertVC.addAction(okAction)
present(
alertVC,
animated: true,
completion: nil)
}
// MARK: Photos Albums
func showImagePicker() {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
// picker.modalPresentationStyle = .Popover
present(picker,
animated: true,
completion: nil)
picker.popoverPresentationController?.sourceView = self.view
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
image = chosenImage
self.performSegue(withIdentifier: "ShowEditView", sender: self)
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: false, completion: nil)
}
// MARK: Seque to EditViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowEditView" {
if let vc = segue.destination as? EditViewController {
vc.image = image
}
}
}
}
My "edit" view controller, which is embedded in a UINavigationBar with a button on it set to System Item == Action:
// MARK: Image actions
#IBAction func shareImage(_ sender: UIBarButtonItem) {
let context = CIContext()
let final = context.createCGImage(imgEdited, from: imgEdited.extent)
let shareImage = UIImage(cgImage: final!)
let vc = UIActivityViewController(activityItems: [shareImage], applicationActivities: [])
vc.excludedActivityTypes = [
//UIActivityTypePostToTwitter,
//UIActivityTypePostToFacebook,
UIActivityType.postToWeibo,
//UIActivityTypeMessage,
//UIActivityTypeMail,
UIActivityType.print,
//UIActivityTypeCopyToPasteboard,
UIActivityType.assignToContact,
//UIActivityTypeSaveToCameraRoll,
UIActivityType.addToReadingList,
//UIActivityTypePostToFlickr,
UIActivityType.postToVimeo,
UIActivityType.postToTencentWeibo
]
present(vc,
animated: true,
completion: nil)
vc.popoverPresentationController?.sourceView = self.view
vc.completionWithItemsHandler = {(activity, success, items, error) in
}
}
Notes:
Keep in mind that when using the UIImagePickerController in an iOS 10 device, it will crash unless you add this to your info.plist:
<key>NSCameraUsageDescription</key>
<string>Used to capture new image for photo effect</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Used to select an image for photo effect</string>
You may use whatever you wish in the tag.
The UIActivityViewController will present all commented out options in it's excludedActivityTypes. (I keep these options listed just for self documentation.) If a user has Facebook and wants to post to it, they'll be prompted to login if they aren't yet.

Importing document with UIDocumentPickerViewController warns "fileprovider plugin was invalidated"

Anytime I import a document via UIDocumentPickerViewController, I see a message logged to the console:
TestApp[66587:1550086] plugin com.apple.UIKit.fileprovider.default invalidated
Does this mean theres something wrong with my code? Or is this just an expected warning? Is there anyway to suppress it?
#IBAction func attachFile(sender: UIButton) {
let documentPicker = UIDocumentPickerViewController(documentTypes: ["public.image"], inMode: .Import)
documentPicker.delegate = self
self.presentViewController(documentPicker, animated: true, completion: nil)
}
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) {
}
I am using xcode 8.3.2 and swift 3.0...Here is my code...it is working well..just call openDocumentPicker() i hope it helps you
extension AddCaseStep3ViewController : UIDocumentMenuDelegate,UIDocumentPickerDelegate{
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
let url = url as URL
//this is the url of your doc you can send enjoy!!
}
#available(iOS 8.0, *)
public func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
//dismiss(animated: true, completion: nil)
}
func openDocumentPicker(){
//
let documentPicker = UIDocumentPickerViewController(documentTypes: ["public.content","public.data","kUTTypePDF"], in: .import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = .formSheet
self.present(documentPicker, animated: true, completion: nil)
}}

Resources