The ActivityViewController works as expected, but I'm getting a memory leak if I pass a URL as an activityItem. This file (archivedFile) is not needed other than for the export.
let fileName = "test.myuti"
let tempDirURL: URL = FileManager.default.temporaryDirectory
let fullWriteURL: URL = tempDirURL.appendingPathComponent(fileName)
let exportCode = ExportCode(mainObject: theExpObject, mainObTitle: theTitle)
let dicToArchive = exportCode.createFileToExport()
let archivedFile = NSKeyedArchiver.archivedData(withRootObject: dicToArchive)
do {
try archivedFile.write(to: fullWriteURL, options: [.atomic])
}
catch {
errAlrt("Could not create an export file")
}
let activityVC = UIActivityViewController(activityItems: [fullWriteURL], applicationActivities: nil)
activityVC.excludedActivityTypes = [.assignToContact, .postToFacebook, .postToTwitter, .addToReadingList, UIActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"), UIActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"), .postToFlickr, .postToWeibo, .saveToCameraRoll, .copyToPasteboard, .openInIBooks, .print, .postToTencentWeibo]
let popCntrl = activityVC.popoverPresentationController
popCntrl?.permittedArrowDirections = .any
popCntrl?.sourceView = self.view
popCntrl?.sourceRect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 200, height: 200))
self.present(activityVC, animated: false, completion: nil)
Related
Trying to share image and link in UIActivityController, But its only share link not the image
code snippet-
let model = self.memeFeedDataList[sender.tag]
let imageURL = NSURL(string: NetWorkingConstants.baseImageURL+model.imageUrl!) //https://xyz.png
let imagedData = NSData(contentsOf: imageURL! as URL)!
let img = [UIImage(data: imagedData as Data)]
let linkURL = NSURL(string:"https://stackoverflow.com/")
let shareAll = [img , linkURL! ] as [Any]
let activity = UIActivityViewController(activityItems: shareAll, applicationActivities: nil);
self.present(activity, animated: true, completion: nil)
Output screenshot-
I am trying to export a PDF with a password protection.
Currently, My app directly exports the PDF File to the iOS Files app...
How do I password protect it before exporting it?
Here's my current code, Please do let me know what I have to change to achive this.
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
guard scan.pageCount >= 1 else {
controller.dismiss(animated: true)
return
}
var arrImages = [UIImage]()
for i in 0...scan.pageCount-1 {
let originalImage = scan.imageOfPage(at: i)
let fixedImage = reloadedImage(originalImage)
arrImages.append(fixedImage)
}
controller.dismiss(animated: true)
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let docURL = documentDirectory.appendingPathComponent("ScannedImage.pdf")
let data = createNewPDF(arrImage: arrImages)
do{
try data?.write(to: docURL)
print("Success")
}catch(let error){
print("error is \(error.localizedDescription)")
}
}
The PDF Creation Functions
func createPDF(image: UIImage) -> NSData? {
let pdfData = NSMutableData()
let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData)!
var mediaBox = CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height)
let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, nil)!
pdfContext.beginPage(mediaBox: &mediaBox)
pdfContext.draw(image.cgImage!, in: mediaBox)
pdfContext.endPage()
let activityViewController = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)
present(activityViewController, animated: true, completion: nil)
return pdfData
}
func createNewPDF(arrImage: [UIImage]) -> Data? {
let pdfDocument = PDFDocument()
for i in 0...arrImage.count-1 {
let pdfPage = PDFPage(image: arrImage[i])
pdfDocument.insert(pdfPage!, at: i)
}
let pdfData = pdfDocument.dataRepresentation()
let activityViewController = UIActivityViewController(activityItems: [pdfData!], applicationActivities: nil)
present(activityViewController, animated: true, completion: nil)
return pdfData
}
Please do let me know if you need anything else....
Thanks in advance!
I am creating a PDF and sharing it via UIActivityViewController.
func createFlyer() -> Data {
// 1
let pdfMetaData = [
kCGPDFContextCreator: "Flyer",
]
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]
// 2
let pageWidth = 8.5 * 72.0
let pageHeight = 11 * 72.0
let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
// 3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
// 4
let data = renderer.pdfData { (context) in
// 5
context.beginPage()
// 6
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
}
return data
}
func sharePDF () {
let activityViewController = UIActivityViewController(
activityItems: [data], applicationActivities: nil)
activityViewController.excludedActivityTypes = [UIActivity.ActivityType.saveToCameraRoll]
if let popoverPresentationController = activityViewController.popoverPresentationController {
popoverPresentationController.barButtonItem = self.sharePDFButton
}
self.present(activityViewController, animated: true, completion: {
})
}
Everything is fine, except for the file name is generated by the system ('PDF Document.pdf').
Is there a way to have a custom file name?
Please try to use below code while presenting activityViewController, I hope it works.
let fileManager = FileManager.default
let documentoPath = getDirectoryPath().appendingPathComponent(url.lastPathComponent) as URL
print("documentoPath :\(documentoPath)")
if fileManager.fileExists(atPath: documentoPath.path) {
DispatchQueue.main.async {
let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [documentoPath], applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.downloadNavController?.present(activityViewController, animated: true, completion: { () in
UIBarButtonItem.appearance().tintColor = UIColor.systemBlue
UINavigationBar.appearance().barTintColor = UIColor.white
})
}
}
You can find getDirectoryPath() here:
func getDirectoryPath() -> URL {
var nestedFolderURL: URL?
do{
let rootFolderURL = try FileManager.default.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false
)
nestedFolderURL = rootFolderURL
if !FileManager.default.fileExists(atPath: nestedFolderURL!.relativePath) {
try FileManager.default.createDirectory(
at: nestedFolderURL!,
withIntermediateDirectories: false,
attributes: nil
)
}
return nestedFolderURL!
} catch (let error) {
print(error)
}
return nestedFolderURL!
}
I found this code that works, but I need to somehow change it so that it prints the entire scroll view. This code only prints whats displaying on the screen.
#IBAction func btnPrint(_ sender: UIBarButtonItem) {
let printArea = pdfDataWithTableView(tableView: tableView)
let activityController = UIActivityViewController(activityItems: [printArea], applicationActivities: nil)
present(activityController, animated: true, completion: nil)
}
func pdfDataWithTableView(tableView: UITableView) {
let priorBounds = tableView.bounds
let fittedSize = tableView.sizeThatFits(CGSize(width:priorBounds.size.width, height:tableView.contentSize.height))
tableView.bounds = CGRect(x:0, y:0, width:fittedSize.width, height:fittedSize.height)
let pdfPageBounds = CGRect(x:0, y:0, width:tableView.frame.width, height:self.view.frame.height)
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds,nil)
var pageOriginY: CGFloat = 0
while pageOriginY < fittedSize.height {
UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil)
UIGraphicsGetCurrentContext()!.saveGState()
UIGraphicsGetCurrentContext()!.translateBy(x: 0, y: -pageOriginY)
tableView.layer.render(in: UIGraphicsGetCurrentContext()!)
UIGraphicsGetCurrentContext()!.restoreGState()
pageOriginY += pdfPageBounds.size.height
}
UIGraphicsEndPDFContext()
tableView.bounds = priorBounds
var docURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
docURL = docURL.appendingPathComponent("myDocument.pdf")
pdfData.write(to: docURL as URL, atomically: true)
}
}
Following up from this question, how would I go about using UIActivityViewController to specify the file type of a file I am sharing over airdrop?
Worked it out:
let myFileManager = FileManager.default
var activityArray = [NSURL]()
activityArray.removeAll()
for (i, data) in dataToShare.enumerated() {
let docsurl = try! myFileManager.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let myurl = docsurl.appendingPathComponent("shareData\(i).gymProf")
var myUrlString = myurl.absoluteString
myUrlString = myUrlString.replacingOccurrences(of: "file://", with: "")
myFileManager.createFile(atPath: myUrlString, contents: data, attributes: nil)
activityArray.append(NSURL(fileURLWithPath: myUrlString))
if myFileManager.fileExists(atPath: myUrlString) {
print("File Exists at \(myUrlString)")
} else {
print("File not found")
}
}
let activityViewController = UIActivityViewController(activityItems: activityArray, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.present(activityViewController, animated: true, completion: nil)