My project calls for me to download a .pdf file, save it locally on an iPad and then craft an email message and send it. Seems pretty straight forward.
Here's the code that does the download:
func downloadFile() {
let urlString = <private url>
let url = URL(string: urlString)!
let downloadTask = URLSession.shared.downloadTask(with: url) {
urlOrNil, responseOrNil, errorOrNil in
// check for and handle errors:
// * errorOrNil should be nil
// * responseOrNil should be an HTTPURLResponse with statusCode in 200..<299
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(url.lastPathComponent)
try? FileManager.default.removeItem(at: savedURL)
try FileManager.default.moveItem(at: fileURL, to: savedURL)
} catch {
print ("file error: \(error)")
self.text = "File Error: \(error)"
}
}
downloadTask.resume()
}
And here's the code that does the crafting of the email message: (I followed this example: https://www.thetopsites.net/article/58693164.shtml) (I've left out some of the boiler plate for brevity)
import SwiftUI
import MessageUI
//import PDFKit
//https://www.thetopsites.net/article/58693164.shtml
struct ContentView: View {
@State var result: Result<MFMailComposeResult, Error>? = nil
@State var isShowingMailView: Bool = false
@State private var text: String = "Foobar"
var body: some View {
Button(action: {
self.isShowingMailView.toggle()
}) {
Text("Mail Me")
}
.disabled(!MFMailComposeViewController.canSendMail())
.sheet(isPresented: $isShowingMailView) {
MailView(result: self.$result)
}
}
struct MailView: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentation
@Binding var result: Result<MFMailComposeResult, Error>?
class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
@Binding var presentation: PresentationMode
@Binding var result: Result<MFMailComposeResult, Error>?
init(presentation: Binding<PresentationMode>,
result: Binding<Result<MFMailComposeResult, Error>?>) {
_presentation = presentation
_result = result
}
func mailComposeController(_ controller: MFMailComposeViewController,
didFinishWith result: MFMailComposeResult,
error: Error?) {
defer {
$presentation.wrappedValue.dismiss()
}
guard error == nil else {
self.result = .failure(error!)
return
}
self.result = .success(result)
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(presentation: presentation,
result: $result)
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
func makeUIViewController(context: UIViewControllerRepresentableContext<MailView>) -> MFMailComposeViewController {
downloadFile()
let urlString = "<privateurl>"
let url = URL(string: urlString)
let vc = MFMailComposeViewController()
vc.mailComposeDelegate = context.coordinator
vc.setToRecipients(["foo@bar.com"])
vc.setMessageBody("Email Test", isHTML: true)
vc.setSubject("email test")
let docDirectory = getDocumentsDirectory()
let filePath = docDirectory.appendingPathComponent("test.pdf")
if let fileData = NSData(contentsOf: filePath) {
print("File data loaded.")
vc.addAttachmentData(fileData as Data, mimeType: "application/pdf", fileName: "foo.pdf")
}
return vc
}
func updateUIViewController(_ uiViewController: MFMailComposeViewController,
context: UIViewControllerRepresentableContext<MailView>) {
}
}
There's no file attached to the email message and I get this error:
[PPT] Error creating the CFMessagePort needed to communicate with PPT.
I haven't had any luck sorting this out. If anybody can offer any thoughts, it would great. Thank you.