I'm trying to share an image using standard UIActivityViewController, it's fine to share on Facebook, Twitter and Save Image using this code:
let firstActivityItem = "foo text"
let secondActivityItem : UIImage = image!
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivityTypePostToWeibo,
UIActivityTypePrint,
UIActivityTypeAssignToContact,
UIActivityTypeAddToReadingList,
UIActivityTypePostToVimeo,
UIActivityTypePostToTencentWeibo
]
self.presentViewController(activityViewController, animated: true, completion: nil)
I need one more thing, Instagram:
If UIApplication.sharedApplication().canOpenURL(instagramURL!) {
// Success
var img = image!
var savePath: String = NSHomeDirectory().stringByAppendingPathComponent("Documents/Test.igo")
UIImageJPEGRepresentation(img, 1).writeToFile(savePath, atomically: true)
var imgURL = NSURL(string: NSString(format: "file://%#", savePath) as! String)
docController = UIDocumentInteractionController(URL: imgURL!) // 1
docController.UTI = "com.instagram.exclusivegram" // 2
docController.delegate = self
docController.annotation = ["InstagramCaption":"testsss"] // 3
docController.presentOpenInMenuFromRect(self.view.frame, inView: self.view, animated: true) // 4
} else {
// Error
}
Both these codes work fine separately, how can I add Instagram to the UIActivityViewController? Is it possible at all?
I think it would be very easier to add other social shares to the code you wrote for Instagram. The ".igo" extension is exclusive for Instagram so other apps will not support it. Just change this extension from ".igo" to ".ig" and other apps will read it:
var savePath: String = NSHomeDirectory().stringByAppendingPathComponent("Documents/Test.ig")
But Instagram also have an exclusive UTI to avoiding other apps to appear in the same Document Interaction View. So you will also need to change it from "exclusivegram" to "photo":
docController.UTI = "com.instagram.photo"
I have an app with a similar functionality and this is my original code:
#IBAction func shareOnIntagram(sender: UIButton) {
let finalImage: UIImage = UIImage.imageWithView(photoView)
let instagramURL = NSURL(string: "instagram://app")
if (UIApplication.sharedApplication().canOpenURL(instagramURL!)) {
let imageData = UIImageJPEGRepresentation(finalImage, 1)
let captionString = "caption"
let writePath = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("instagram.ig")
if imageData?.writeToFile(writePath, atomically: true) == false {
return
} else {
let fileURL = NSURL(fileURLWithPath: writePath)
self.documentController = UIDocumentInteractionController(URL: fileURL)
self.documentController.delegate = self
self.documentController.UTI = "com.instagram.photo"
self.documentController.annotation = NSDictionary(object: captionString, forKey: "InstagramCaption")
self.documentController.presentOpenInMenuFromRect(self.view.frame, inView: self.view, animated: true)
}
} else {
print(" Instagram is not installed ")
}
}
To make this code work, don't forget to add UIDocumentInteractionControllerDelegate in the UIViewController class.
It seems it's not possible, because of .igo extension which is needed by Instagram.
Related
I have a WKWebView which displayed pdf. I want to share the file to another devices such as iPad, iPhone.... using the share button. I tried to display the pdf in preview so it will have the iOS share button the code below.
import UIKit
import WebKit
class ShowPDFView: UIViewController, UIDocumentInteractionControllerDelegate {
#IBAction func SharePDFFile(_ sender: Any) {
let fileName = "testPDF"
guard let urlPath = Bundle.main.url(forResource: fileName, withExtension: "pdf") else {return}
let controller = UIDocumentInteractionController(url: urlPath)
controller.delegate = self
controller.presentPreview(animated: true)
}
func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController!) -> UIViewController! {
return self
}
func documentInteractionControllerViewForPreview(controller: UIDocumentInteractionController!) -> UIView! {
return self.view
}
func documentInteractionControllerRectForPreview(controller: UIDocumentInteractionController!) -> CGRect{
return self.view.frame
}
I got runtime error.
[MC] Reading from private effective user settings.
The preview does not loaded. Does anyone know why?
This function works for me. In Swift 4
#IBAction func SharePDFFile(_ sender: Any) {
let fm = FileManager.default
var pdfURL = (fm.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
pdfURL = pdfURL.appendingPathComponent("johnMilky.pdf") as URL
//Rename document name to "myFile.pdf"
let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("johnMilkyFile.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 = [UIActivity.ActivityType.airDrop]
activitycontroller.popoverPresentationController?.sourceView = self.view
self.present(activitycontroller, animated: true, completion: nil)
}
catch {
print(error)
}
}
Now, I'm developing iOS, Android App. I wish to add a feature, easily sharing an image from my App to Instagram Story, directly. For example, tap button on my App, then transition to Instagram Story, and the user can share on Story.
I searched for some API, nothing to find a good way. Please tell me is possible to develop such a feature.
#IBAction func shareOnInstagram(_ sender: Any) {
DispatchQueue.main.async {
//Share To Instagram:
let instagramURL = URL(string: "instagram://app")
if UIApplication.shared.canOpenURL(instagramURL!) {
let imageData = UIImageJPEGRepresentation(image, 100)
let writePath = (NSTemporaryDirectory() as NSString).appendingPathComponent("instagram.igo")
do {
try imageData?.write(to: URL(fileURLWithPath: writePath), options: .atomic)
} catch {
print(error)
}
let fileURL = URL(fileURLWithPath: writePath)
self.documentController = UIDocumentInteractionController(url: fileURL)
self.documentController.delegate = self
self.documentController.uti = "com.instagram.exlusivegram"
if UIDevice.current.userInterfaceIdiom == .phone {
self.documentController.presentOpenInMenu(from: self.view.bounds, in: self.view, animated: true)
} else {
self.documentController.presentOpenInMenu(from: self.IGBarButton, animated: true)
}
} else {
print(" Instagram is not installed ")
}
}
}
You can use above code to share to Instagram and you need to set instagram in LSApplicationQueriesSchemes in project's info.plist
try this:-
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) //.image to share image and .video to share video
if let lastAsset = fetchResult.firstObject {
let localIdentifier = lastAsset.localIdentifier
let u = "instagram://library?LocalIdentifier=" + localIdentifier
let url = NSURL(string: u)!
if UIApplication.shared.canOpenURL(url as URL) {
UIApplication.shared.open(URL(string: u)!, options: [:], completionHandler: nil)
} else {
let urlStr = "https://itunes.apple.com/in/app/instagram/id389801252?mt=8"
if #available(iOS 10.0, *) {
UIApplication.shared.open(URL(string: urlStr)!, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(URL(string: urlStr)!)
}
}
}
I have in my app button to share image via whatsapp and it does work. But there is some strange thing appears in the menu of UIDocumentInteractionController on some devices.
This is the code:
let urlWhats = "whatsapp://app"
if let urlString = urlWhats.addingPercentEncoding(withAllowedCharacters:CharacterSet.urlQueryAllowed) {
if let whatsappURL = URL(string: urlString) {
if UIApplication.shared.canOpenURL(whatsappURL as URL) {
if let imageData = UIImageJPEGRepresentation(self.ivFramedPicture.image!, 1.0) {
let tempFile = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Documents/whatsAppTmp.wai")
do {
try imageData.write(to: tempFile, options: .atomic)
self.documentInteractionController = UIDocumentInteractionController(url: tempFile)
self.documentInteractionController.delegate = self
self.documentInteractionController.uti = "net.whatsapp.image"
self.documentInteractionController.presentOpenInMenu(from: CGRect.zero, in: self.view, animated: true)
} catch {
print(error)
}
}
} else {
// Cannot open whatsapp
}
}
}
If I click on the 1 whatsapp icon it sends some file that doesn't open on iPhones (Android opens that file like image)
Does anyone can help to resolve that problem? I want only one icon with share image, that's it. Thanks
Simply use UIActivityController for sharing functionality instead of all that code.
Example:
if let image = self.ivFramedPicture.image
{
let activityViewController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)
}
Maybe try using the UIActivityViewController
I'm getting a weird behaviour when sharing a simple PDF document using Swift on IOS. Basicaly if I create it and share it to be printed the image it should contain is not included. If I first display it using a UIViewController and then share it it's fine. I just don't get why !
Here are the interresting parts of my code :
func getHtml() -> String {
// Create a HTML document to be printed
// Save data to file
let fileName = "noteImage.jpeg"
let pathToInvoiceHTMLTemplate = Bundle.main.path(forResource: "note", ofType: "html")
let tmpDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
let fileURL = tmpDirectoryURL.appendingPathComponent(fileName)
let mergedImages = getMergedImages()
//let pngImageData = UIImagePNGRepresentation(image)
let imageData = UIImageJPEGRepresentation(mergedImages, 1.0) // if you want to save as JPEG
try? imageData!.write(to: URL(fileURLWithPath: fileURL.path), options: [.atomic])
var htmlText = "<html><body><b>Problem Retrieving Note Template</b></body></html>"
do {
// Load the note HTML template code into a String variable.
htmlText = try String(contentsOfFile: pathToInvoiceHTMLTemplate!)
// Replace the variables in HTML.
htmlText = htmlText.replacingOccurrences(of: "__PROJECT_NAME__", with: projectName!)
htmlText = htmlText.replacingOccurrences(of: "__NOTE_NAME__", with: note!.name)
htmlText = htmlText.replacingOccurrences(of: "__NOTE_IMAGE__", with: "file:"+fileURL.path)
}
catch {
print("Unable to open and use HTML template files.")
}
return htmlText
}
func getPdf() -> NSMutableData {
// Create a PDF document from the HTML to be shared
// Format HTML
let fmt = UIMarkupTextPrintFormatter(markupText: getHtml())
// Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(fmt, startingAtPageAt: 0)
// Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
let printable = page.insetBy(dx: 0, dy: 0)
render.setValue(NSValue(cgRect: page), forKey: "paperRect")
render.setValue(NSValue(cgRect: printable), forKey: "printableRect")
// Create PDF context and draw
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
return pdfData
}
#IBAction func shareNote(_ sender: UIBarButtonItem) {
// Called in direct sharing
let firstActivityItem = "Text int the message"
let docToShare = getPdf()
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, docToShare], applicationActivities: nil)
// This lines is for the popover you need to show in iPad
activityViewController.popoverPresentationController?.barButtonItem = sender
// This line remove the arrow of the popover to show in iPad
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)
// Anything you want to exclude
activityViewController.excludedActivityTypes = [
UIActivityType.postToWeibo,
UIActivityType.assignToContact,
UIActivityType.saveToCameraRoll,
UIActivityType.addToReadingList,
UIActivityType.postToFlickr,
UIActivityType.postToVimeo,
UIActivityType.postToTencentWeibo,
]
self.present(activityViewController, animated: true, completion: nil)
}
#IBAction func shareDocument(_ sender: UIBarButtonItem) {
// Called in the preview controller when the HTML is displayed
let firstActivityItem = "Text in the message"
let docToShare = getPdf()
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, docToShare], applicationActivities: nil)
// This lines is for the popover you need to show in iPad
activityViewController.popoverPresentationController?.barButtonItem = sender
// This line remove the arrow of the popover to show in iPad
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)
// Anything you want to exclude
activityViewController.excludedActivityTypes = [
UIActivityType.postToWeibo,
UIActivityType.assignToContact,
UIActivityType.saveToCameraRoll,
UIActivityType.addToReadingList,
UIActivityType.postToFlickr,
UIActivityType.postToVimeo,
UIActivityType.postToTencentWeibo,
]
self.present(activityViewController, animated: true, completion: nil)
}
Does anybody have a clue ?
I found a workaround to my problem :
The only solution I found so far is to create a dummy UIWebView that I hide. I load the HTML in the UIWebView and then create the PDF. Here is my code :
override func viewDidLoad() {
super.viewDidLoad()
hiddenWebView.loadHTMLString(htmlText, baseURL: nil)
hiddenWebView.isHidden = true
}
override func viewDidAppear(_ animated: Bool) {
pdfDocument = getPdf()
let tmpDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
let fileURL = tmpDirectoryURL.appendingPathComponent("document.pdf")
pdfDocument.write(to: fileURL, atomically: false)
documentWebView.loadRequest(URLRequest(url: fileURL))
}
I have write this code to show pdf using UIDocumentInteractionController.But,I don't know how to search pdf at local directory and open in iOS 8 and below..Any help?
let filename = history.invoiceLongDate // 01223642
if !filename.isEmpty{
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docs = paths[0]
let pathURL = NSURL(fileURLWithPath: docs, isDirectory: true)
if #available(iOS 9.0, *) {
let fileURL = NSURL(fileURLWithPath: "\(filename)_my_invoice.pdf", isDirectory: false, relativeToURL: pathURL)
self.docController = UIDocumentInteractionController(URL: fileURL)
self.docController?.delegate = self
self.docController?.presentOptionsMenuFromRect(sender.frame, inView: self.view, animated: true)
} else {
// Fallback on earlier versions
// Any Help with that?
}
}
You can view PDF in iOS 8 by using webview. Try below code,
if let pdf = NSBundle.mainBundle().URLForResource("myPDF", withExtension: "pdf", subdirectory: nil, localization: nil) {
let req = NSURLRequest(URL: pdf)
let webView = UIWebView(frame: CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height))
webView.loadRequest(req)
self.view.addSubview(webView)
}
OR
if let baseUrl = NSURL.fileURLWithPath(pathURL) {
let fileURL = baseUrl.URLByAppendingPathComponent(NFConstants.NFCoreDataStringIdentifiers.CoreDataStoresPathComponent.rawValue)
}
Hope this will be helpful to you.
UIDocumentInteractionController is available with (iOS 3.2, *).
For Viewing PDF file:
var documentInteractionController: UIDocumentInteractionController!
#IBAction func openDocument(sender: UIButton) {
let URL: NSURL = NSBundle.mainBundle().URLForResource("pdf-sample", withExtension: "pdf")!
if (URL != "") {
// Initialize Document Interaction Controller
self.documentInteractionController = UIDocumentInteractionController(URL: URL)
// Configure Document Interaction Controller
self.documentInteractionController.delegate = self
// Present Open In Menu
self.documentInteractionController.presentOptionsMenuFromRect(sender.frame, inView: self.view, animated: true)
//presentOpenInMenuFromRect(button.frame, inView: self.view, animated: true)
}
}
// MARK: UIDocumentInteractionControllerDelegate
func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController) -> UIViewController {
return self
}