I'm trying to share a csv file using UIActivityViewController.
I want to share both through email and other applications, like Telegram.
Through Telegram the file gets shared correctly, but using email, the email has no attachments.
Also, the csv file has no extension, should I set a MIME type? How?
#IBAction func shareSheet(sender: AnyObject) {
let firstActivityItem = "Hi, here is the csv file"
//do i really need this? what for?
let secondActivityItem : NSURL = NSURL(string: "http//:urlyouwant")!
let csv : NSData! = NSData(contentsOfFile: NSTemporaryDirectory() + "export.csv")
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem, csv], applicationActivities: nil)
//set the email title
activityViewController.setValue(firstAcxtivityItem, forKey: "subject")
self.presentViewController(activityViewController, animated: true, completion: nil)
}
This is the code I use to send a CSV via the mail composer
let csvString = "Your CSV String"
let subject = "Subject of your email"
let fileName = "CSV Filename.csv"
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
composeVC.setSubject(subject)
if let csvData = csvString.data(using: String.Encoding.utf8) {
composeVC.addAttachmentData(csvData, mimeType: "text/csv", fileName: fileName)
}
self.present(composeVC, animated: true, completion: nil)
Related
I am unable to share the msword and msexcel and ppt files in Swift Using UIActivityViewController
Here is the code snippet I am using
func ShareFileFromApptoIpad(filename : String!){
let fileManager = FileManager.default
let documentoPath = (self.getDirectoryPath() as NSString).appendingPathComponent("\(filename!)")
print("doc\(documentoPath)")
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")
}
}
you can change your url Like this
let url = NSURL.fileURL(withPath: myFileName)
and then use in
let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)
I'm trying to share a location from my iOS app to WhatsApp and I want it to look like this:
What I'm doing is sending vCard with this code :
func vCardURL(from coordinate: CLLocationCoordinate2D, with name: String?) -> URL {
let vCardFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Shared Location.loc.vcf")
let vCardString = [
"BEGIN:VCARD",
"VERSION:3.0",
//"PRODID:-//Apple Inc.//iPhone OS 10.3.2//EN",
"N:;My Location;;;",
"FN:My Location",
"item1.URL;type=pref:https://maps.apple.com/?ll=50.359890\\,12.934560&q=My%20Location&t=m",
"item1.X-ABLabel:map url",
"END:VCARD"
].joined(separator: "\n")
do {
try vCardString.write(toFile: vCardFileURL.path, atomically: true, encoding: .utf8)
} catch let error {
print("Error, \(error.localizedDescription), saving vCard: \(vCardString) to file path: \(vCardFileURL.path).")
}
print(vCardString)
return vCardFileURL
} // end of function
// calling the methood above
let vURL = LocationVCard.vCardURL(from: self.newLocation.coordinate, with: "Berlin")
let activityViewController = UIActivityViewController(activityItems: [vURL], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)
But I always end up with this style instead of what I want:
No need to save the vCard string to a file, just convert it to Data and wrap it with NSItemProvider with the correct type identifier public.vcard, and it'll work just fine:
let data = vCardString.data(using: .utf8)! as NSData
let item = NSItemProvider(item: data, typeIdentifier: "public.vcard")
let activityViewController = UIActivityViewController(activityItems: [item], applicationActivities: nil)
I am using this code to export CSV file https://gist.github.com/kenechilearnscode/2d5d35f550f593332319
And it is exporting correctly but I want to email this CSV using MFMailComposeViewController. The above code opens an applicationActivities from where I can choose mail and the file is attached but the subject and recipients are not set. Code I am using to email the CSV is following. Its setting the subject and recipients etc but not attaching the CSV file.
if( MFMailComposeViewController.canSendMail() ) {
print("Can send email.")
let mailComposer = MFMailComposeViewController()
mailComposer.mailComposeDelegate = self
//Set the subject and message of the email
mailComposer.setSubject("Patient Data")
mailComposer.setMessageBody("Please find attached herewith complete patient data", isHTML: false)
mailComposer.setToRecipients(secondaryEmailList)
mailComposer.setCcRecipients([masterEmail])
if let filePath = Bundle.main.path(forResource: "export", ofType: "csv") {
print("File path loaded.")
if let fileData = NSData(contentsOfFile: filePath) {
print("File data loaded.")
mailComposer.addAttachmentData(fileData as Data, mimeType: "text/csv", fileName: "export")
}
}
self.present(mailComposer, animated: true, completion: nil)
}
Here is the code I am using to generate CSV file
func saveAndExport(exportString: String) {
let exportFilePath = NSTemporaryDirectory() + "export.csv"
let exportFileURL = NSURL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
var fileHandleError: NSError? = nil
var fileHandle: FileHandle? = nil
do {
fileHandle = try FileHandle(forWritingTo: exportFileURL as URL)
} catch {
print("Error with fileHandle")
}
if fileHandle != nil {
fileHandle!.seekToEndOfFile()
let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
fileHandle!.write(csvData!)
fileHandle!.closeFile()
let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivityType.assignToContact,
UIActivityType.saveToCameraRoll,
UIActivityType.postToFlickr,
UIActivityType.postToVimeo,
UIActivityType.postToTencentWeibo
]
self.present(activityViewController, animated: true, completion: nil)
}
}
I want to share some files I have locally in my app using Share Sheet functionality on iPhone. I display the file in a UIWebView and when the user clicks the share sheet, I want to show options (email, WhatsApp, etc. ) to share the file displayed on the UIWebView. I know that we can use
func displayShareSheet(shareContent:String) {
let activityViewController = UIActivityViewController(activityItems: [shareContent as NSString], applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: {})
}
to share a string for example. How do I change this code to share documents?
Swift 4.2 and Swift 5
If you already have a file in a directory and want to share it, just add it's URL into activityItems:
let fileURL = NSURL(fileURLWithPath: "The path where the file you want to share is located")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the file to the Array
filesToShare.append(fileURL)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
If you need to make the file:
I'm using this extension to make files from Data (read the comments in the code for explanation how it works):
As in the typedef's answer, get the current documents directory:
/// Get the current directory
///
/// - Returns: the Current directory in NSURL
func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory as NSString
}
Extension for Data:
extension Data {
/// Data into file
///
/// - Parameters:
/// - fileName: the Name of the file you want to write
/// - Returns: Returns the URL where the new file is located in NSURL
func dataToFile(fileName: String) -> NSURL? {
// Make a constant from the data
let data = self
// Make the file path (with the filename) where the file will be loacated after it is created
let filePath = getDocumentsDirectory().appendingPathComponent(fileName)
do {
// Write the file from data into the filepath (if there will be an error, the code jumps to the catch block below)
try data.write(to: URL(fileURLWithPath: filePath))
// Returns the URL where the new file is located in NSURL
return NSURL(fileURLWithPath: filePath)
} catch {
// Prints the localized description of the error from the do block
print("Error writing the file: \(error.localizedDescription)")
}
// Returns nil if there was an error in the do-catch -block
return nil
}
}
Examples how to use:
Share image-files:
// Your image
let yourImage = UIImage()
in png-file
// Convert the image into png image data
let pngImageData = yourImage.pngData()
// Write the png image into a filepath and return the filepath in NSURL
let pngImageURL = pngImageData?.dataToFile(fileName: "nameOfYourImageFile.png")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of png image to the Array
filesToShare.append(pngImageURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
in jpg-file
// Convert the image into jpeg image data. compressionQuality is the quality-compression ratio in % (from 0.0 (0%) to 1.0 (100%)); 1 is the best quality but have bigger filesize
let jpgImageData = yourImage.jpegData(compressionQuality: 1.0)
// Write the jpg image into a filepath and return the filepath in NSURL
let jpgImageURL = jpgImageData?.dataToFile(fileName: "nameOfYourImageFile.jpg")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of jpg image to the Array
filesToShare.append(jpgImageURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
Share text-files:
// Your String including the text you want share in a file
let text = "yourText"
// Convert the String into Data
let textData = text.data(using: .utf8)
// Write the text into a filepath and return the filepath in NSURL
// Specify the file type you want the file be by changing the end of the filename (.txt, .json, .pdf...)
let textURL = textData?.dataToFile(fileName: "nameOfYourFile.txt")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the text file to the Array
filesToShare.append(textURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
Other files:
You can make a file from anything which is in Data format and as far as I know, almost everything in Swift can be converted into Data like String, Int, Double, Any...:
// the Data you want to share as a file
let data = Data()
// Write the data into a filepath and return the filepath in NSURL
// Change the file-extension to specify the filetype (.txt, .json, .pdf, .png, .jpg, .tiff...)
let fileURL = data.dataToFile(fileName: "nameOfYourFile.extension")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the file to the Array
filesToShare.append(fileURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
I want to share my solution of UIActivityViewController and sharing text as a image file. This solution works for sharing via Mail and even Save to Dropbox.
#IBAction func shareCsv(sender: AnyObject) {
//Your CSV text
let str = self.descriptionText.text!
filename = getDocumentsDirectory().stringByAppendingPathComponent("file.png")
do {
try str.writeToFile(filename!, atomically: true, encoding: NSUTF8StringEncoding)
let fileURL = NSURL(fileURLWithPath: filename!)
let objectsToShare = [fileURL]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion: nil)
} catch {
print("cannot write file")
// failed to write file – bad permissions, bad filename, missing permissions, or more likely it can't be converted to the encoding
}
}
func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
Here's the Swift 3 version:
let dictToSave: [String: Any] = [
"someKey": "someValue"
]
let jsonData = try JSONSerialization.data(withJSONObject: dictToSave, options: .prettyPrinted)
let filename = "\(self.getDocumentsDirectory())/filename.extension"
let fileURL = URL(fileURLWithPath: filename)
try jsonData.write(to: fileURL, options: .atomic)
let vc = UIActivityViewController(activityItems: [fileURL], applicationActivities: [])
self.present(vc, animated: true)
func getDocumentsDirectory() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
I am experiencing a few issue with the Share option in iOS8.
With the below code I am able to correctly share by Email and Text(SMS) including my text strings and my image.
But when I try to share to Facebook, the generated post only includes my image (skipping the text strings) while if I try to share on WhatsApp, the image is skipped and only the text strings are passed.
Does anybody have any suggestion?
My code:
#IBAction func shareButtonClicked(sender: UIBarButtonItem) {
var kidToShare1 : String? = noKids
if selectedKid == nil {
kidToShare1 = noKids
println("kid is nil")
} else {
kidToShare1 = selectedKid!.kidName
}
let kidToShare = NSLocalizedString("Kid: ", comment:"Kid to share") + kidToShare1!
let imageToShare = photo! ?? noPhoto!
let textToShare = NSLocalizedString("Event Description: ", comment:"Text to share") + descriptionText as NSString
let dateToShare = NSLocalizedString("Event Date: ", comment: "Date to share") + formatDate(date) as NSString
let message = NSLocalizedString("My App", comment: "Main sharing message")
let objectsToShare = [message, dateToShare, kidToShare, textToShare, imageToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.excludedActivityTypes = [UIActivityTypeAirDrop, UIActivityTypeAirDrop, UIActivityTypeAssignToContact, UIActivityTypeAddToReadingList,UIActivityTypeCopyToPasteboard,UIActivityTypeSaveToCameraRoll,UIActivityTypePrint]
self.presentViewController(activityVC, animated: true, completion: nil)
}
}