share PDF file with UIActivityViewController - ios

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

Related

Sharing text and Url to Facebook Messenger with UIActivityViewController but failing

I want to share both text and url to Facebook Messenger using UIActivityViewController.
But when i success send and open my Messenger, i only get url.
Is it possible send text and url to Facebook Messenger using UIActivityViewController at the same time?
Here is my code
#IBAction func sharedLink(_ sender: Any) {
let url = NSURL(string: "https://www.google.com.tw")!
let text = "test" as AnyObject
let shareObject: [AnyObject] = [text, url as AnyObject]
let vc = UIActivityViewController(activityItems: shareObject, applicationActivities: [])
vc.completionWithItemsHandler = { (type,completed,items,error) in
if completed { vc.dismiss(animated: true, completion: nil) }
}
present(vc, animated: true, completion: nil)
}
Here is my screenshot
In my case,
#IBAction func sharedLink(_ sender: Any) {
let urlString = "https://www.google.com.tw"
let url = NSURL(string: urlString)!
let text = "test" as AnyObject
let shareObject: [AnyObject] = ["\(text), \(urlString)"]
let vc = UIActivityViewController(activityItems: shareObject, applicationActivities: [])
vc.completionWithItemsHandler = { (type,completed,items,error) in
if completed { vc.dismiss(animated: true, completion: nil) }
}
present(vc, animated: true, completion: nil)
}

How to embed text to animated gif and save the gif?

I am trying to save the gif with embedded text on it.
I tried adding subview on top of the gif and make the view transparent but I don't know how to add both files and save them as one.
#IBAction func shareAction(_ sender: Any) {
let shareImage = generateMemedImage()
let data = shareImage.pngData()! as NSData
let nsdata:NSData = NSData(contentsOf: gifurl)!
var array:[NSData] = []
array.append(data)
array.append(nsdata)
let activityController = UIActivityViewController(activityItems: array, applicationActivities: nil)
present(activityController, animated: true, completion: nil)
activityController.completionWithItemsHandler = {(activity, completed, items, error) in
if (completed){
// self.save()
self.navigationController?.popViewController(animated: true)
self.dismiss(animated: true, completion: nil)
}
}
}
func generateMemedImage() -> UIImage {
// Render view to an image
topToolbar.isHidden = true
bottomToolBar.isHidden = true
UIGraphicsBeginImageContext(self.view.frame.size)
view.drawHierarchy(in: self.view.frame, afterScreenUpdates: true)
let memedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
topToolbar.isHidden = false
bottomToolBar.isHidden = false
return memedImage
}

Document Picker View Controller issue in Swift

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
}

How to get and show screenshot in share button?

Below I have tried to code so the screenShot function will take a full screenshot of my viewController. I am trying to figure out how I could take the screenshot and put it in into my activityItems in the sharePressed action, so it will show the screenshot when you try to share.
func captureScreen() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
#IBAction func sharePressed(_ sender: Any) {
let activityVC = UIActivityViewController(activityItems: [""], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view
self.present(activityVC, animated: true, completion: nil)
}
#IBAction func sharePressed(_ sender: Any) {
let imgScreenshot = captureScreen()
if let imgScreenshot = imgScreenshot {
let objectsToShare = ["Post message", imgScreenshot] as [Any]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.excludedActivityTypes = [UIActivityType.airDrop, UIActivityType.addToReadingList]
self.present(activityVC, animated: true, completion: nil)
}
}

How to implement "share button" in Swift

This is the some peace of code for twitter... I want to know how to get the share action view like we get in iOS stock photos app...
#IBAction func twitterButton(sender: AnyObject) {
let image: UIImage = UIImage(named: "LaunchScreenImage.png")!
let twitterControl = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
twitterControl.setInitialText("")
twitterControl.addImage(image)
let completionHandler = {(result:SLComposeViewControllerResult) -> () in
twitterControl.dismissViewControllerAnimated(true, completion: nil)
switch(result){
case SLComposeViewControllerResult.Cancelled:
print("User canceled", terminator: "")
case SLComposeViewControllerResult.Done:
print("User tweeted", terminator: "")
}
}
twitterControl.completionHandler = completionHandler
self.presentViewController(twitterControl, animated: true, completion: nil)
}
Swift 5:
// Setting description
let firstActivityItem = "Description you want.."
// Setting url
let secondActivityItem : NSURL = NSURL(string: "http://your-url.com/")!
// If you want to use an image
let image : UIImage = UIImage(named: "your-image-name")!
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem, image], applicationActivities: nil)
// This lines is for the popover you need to show in iPad
activityViewController.popoverPresentationController?.sourceView = (sender as! UIButton)
// This line remove the arrow of the popover to show in iPad
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)
// Pre-configuring activity items
activityViewController.activityItemsConfiguration = [
UIActivity.ActivityType.message
] as? UIActivityItemsConfigurationReading
// Anything you want to exclude
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.postToWeibo,
UIActivity.ActivityType.print,
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.addToReadingList,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo,
UIActivity.ActivityType.postToFacebook
]
activityViewController.isModalInPresentation = true
self.present(activityViewController, animated: true, completion: nil)
This is how I implemented sharing with Swift 4/5 using a right button on the Navigation Controller. It includes an image, text and link.
SWIFT 4/5
On ViewDidLoad
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Share", style: .plain, target: self, action: #selector(share(sender:)))
Create the function
#objc func share(sender:UIView){
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let textToShare = "Check out my app"
if let myWebsite = URL(string: "http://itunes.apple.com/app/idXXXXXXXXX") {//Enter link to your app here
let objectsToShare = [textToShare, myWebsite, image ?? #imageLiteral(resourceName: "app-logo")] as [Any]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
//Excluded Activities
activityVC.excludedActivityTypes = [UIActivity.ActivityType.airDrop, UIActivity.ActivityType.addToReadingList]
//
activityVC.popoverPresentationController?.sourceView = sender
self.present(activityVC, animated: true, completion: nil)
} }
#IBAction func shareButtonClicked(sender: AnyObject)
{
//Set the default sharing message.
let message = "Message goes here."
//Set the link to share.
if let link = NSURL(string: "http://yoururl.com")
{
let objectsToShare = [message,link]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.excludedActivityTypes = [UIActivityTypeAirDrop, UIActivityTypeAddToReadingList]
self.presentViewController(activityVC, animated: true, completion: nil)
}
}
This will allow you to present a UIActivityViewController to share a link and a message with any application that will accept them.
Details
Xcode 11.4.1 (11E503a), Swift 5.2
Solution
TopViewController solution
extension UIApplication {
class var topViewController: UIViewController? { return getTopViewController() }
private class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController { return getTopViewController(base: nav.visibleViewController) }
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController { return getTopViewController(base: selected) }
}
if let presented = base?.presentedViewController { return getTopViewController(base: presented) }
return base
}
private class func _share(_ data: [Any],
applicationActivities: [UIActivity]?,
setupViewControllerCompletion: ((UIActivityViewController) -> Void)?) {
let activityViewController = UIActivityViewController(activityItems: data, applicationActivities: nil)
setupViewControllerCompletion?(activityViewController)
UIApplication.topViewController?.present(activityViewController, animated: true, completion: nil)
}
class func share(_ data: Any...,
applicationActivities: [UIActivity]? = nil,
setupViewControllerCompletion: ((UIActivityViewController) -> Void)? = nil) {
_share(data, applicationActivities: applicationActivities, setupViewControllerCompletion: setupViewControllerCompletion)
}
class func share(_ data: [Any],
applicationActivities: [UIActivity]? = nil,
setupViewControllerCompletion: ((UIActivityViewController) -> Void)? = nil) {
_share(data, applicationActivities: applicationActivities, setupViewControllerCompletion: setupViewControllerCompletion)
}
}
Usage
UIApplication.share("Text to share")
let data = ["Text, Image and url", image, url] as [Any]
UIApplication.share(data)
Full sample
Do not forget to add the solution code here (look above)
import UIKit
class ViewController: UIViewController {
private weak var imageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
var button = UIButton(frame: CGRect(x: 50, y: 50, width: 200, height: 40))
button.setTitle("Share text", for: .normal)
button.addTarget(self, action: #selector(shareButtonTapped), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
button = UIButton(frame: CGRect(x: 50, y: 80, width: 200, height: 40))
button.setTitle("Share text & image", for: .normal)
button.addTarget(self, action: #selector(shareCombinedData), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
let imageView = UIImageView(frame: CGRect(x: 50, y: 120, width: 200, height: 200))
imageView.image = UIImage(named: "image")
imageView.isUserInteractionEnabled = true
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageViewTapped)))
view.addSubview(imageView)
self.imageView = imageView
}
#objc func shareButtonTapped() { UIApplication.share("Text to share") }
#objc func imageViewTapped() {
guard let image = imageView?.image else { return }
UIApplication.share(image)
}
#objc func shareCombinedData() {
guard let image = imageView?.image, let url = URL(string: "http://google.com") else { return }
let data = ["Text, Image and url", image, url] as [Any]
UIApplication.share(data)
}
}
Sample result
I develop #onemillion 's answer:) You can use this for Swift 3
override func viewDidLoad() {
super.viewDidLoad()
share(message: "selam", link: "htttp://google.com")
}
func share(message: String, link: String) {
if let link = NSURL(string: link) {
let objectsToShare = [message,link] as [Any]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
}
UPDATED FOR SWIFT 3.0
// first function to add the button to your navigation bar
func addingNavBarBtn () {
// setting button's image
let comunicateImage = UIImage(named: "NavfShare")
let comunicateBtn = UIBarButtonItem(image: comunicateImage, style: .plain, target: self, action: #selector(shareButtonPressed))
comunicateBtn.tintColor = UIColor.white
self.navigationItem.rightBarButtonItem = comunicateBtn
}
//setting button's action
func shareButtonPressed(){
//checking the object and the link you want to share
let urlString = "https://www.google.com"
let linkToShare = [urlString!]
let activityController = UIActivityViewController(activityItems: linkToShare, applicationActivities: nil)
self.present(activityController, animated: true, completion: nil)
}
let items = ["Your Sharing Content"];
let activity = UIActivityViewController(activityItems: items, applicationActivities: nil);
self.present(activity, animated: true, completion: nil)
Improving on JP Aquino's code for Swift 5 for share action rightBarButtonItem on the Navigation Controller.
In viewDidLoad of your ViewController, do this:
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareBarButtonItemClicked(_:)))
Then implement the shareBarButtonItemClicked method as below somewhere inside your ViewController:
#objc func shareBarButtonItemClicked(_ sender: UIBarButtonItem) {
// Text to share with other apps
let textToShare = String(describing: "My awesome app")
// URL, and or, and image to share with other apps
guard let myAppURLToShare = URL(string: "http://itunes.apple.com/app/idXXXXXXXXX"), let image = UIImage(named: "image.jpg") else {
return
}
let items = [textToShare, myAppURLToShare, image] as [Any]
let avc = UIActivityViewController(activityItems: items, applicationActivities: nil)
//Apps to exclude sharing to
avc.excludedActivityTypes = [
UIActivityType.airDrop,
UIActivityType.print,
UIActivityType.saveToCameraRoll,
UIActivityType.addToReadingList
]
//If user on iPad
if UIDevice.current.userInterfaceIdiom == .pad {
if avc.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
avc.popoverPresentationController?.barButtonItem = sender
}
}
//Present the shareView on iPhone
self.present(avc, animated: true, completion: nil)
}
Happy coding!
#IBAction func shareButtonAction(_ sender: UIButton) {
let activityVC = UIActivityViewController(activityItems: ["Whatever you want to share"], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = sender
present(activityVC, animated: true, completion: nil)
activityVC.completionWithItemsHandler = { (activityType, completed:Bool, returnedItems:[Any]?, error: Error?) in
if completed {
self.dismiss(animated: true, completion: nil)
}
}
}
IOS 16
As of IOS 16 there is now a sharelink button, just pass in your link as the link.
#available(iOS 16.0, *)
ShareLink(item: link) {
Label("Click To Share", systemImage: "swift")
}

Resources