Unfortunately, it is nearly impossible to create a .docx
file in Swift, given how complicated they are (you can see for yourself by changing the file extension on any old .docx
file to .zip
, which will reveal their inner structure). The next best thing is to simply create a .txt
file, which can also be opened into Pages (though sadly not Docs). If you're looking for a more polished format, complete with formatting and possibly even images, you could choose to create a .pdf
file.
Here are some code samples that might be of assistance:
Creating and sharing a .txt
file in Swift 3:
func export(_ string: String, title: String) throws {
// create a file path in a temporary directory
let fileName = "\(title).txt"
let filePath = (NSTemporaryDirectory() as NSString).appendingPathComponent(fileName)
// save the string to the file
try string.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8)
// open share dialog
// Initialize Document Interaction Controller
self.interactionController = UIDocumentInteractionController(url: URL(fileURLWithPath: filePath))
// Configure Document Interaction Controller
self.interactionController!.delegate = self
// Present Open In Menu
self.interactionController!.presentOptionsMenu(from: yourexportbarbuttonoutlet, animated: true) // create an outlet from an Export bar button outlet, then use it as the `from` argument
}
This can be called with
export("Hello World", title: "HelloWorld")
to instantly create a txt file and open the share dialog for it.
Creating and sharing a simple .pdf
file in Swift 3:
func openPDF(_ string: String, title: String) throws {
// 1. Create a print formatter
let html = "\(title)
\(string)
" // create some text as the body of the PDF with html.
let fmt = UIMarkupTextPrintFormatter(markupText: html)
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(fmt, startingAtPageAt: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 10, y: 10, width: 595.2, height: 841.8) // A4, 72 dpi, x and y are horizontal and vertical margins
let printable = page.insetBy(dx: 0, dy: 0)
render.setValue(NSValue(cgRect: page), forKey: "paperRect")
render.setValue(NSValue(cgRect: printable), forKey: "printableRect")
// 4. 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();
// 5. Save PDF file
var path = "\(NSTemporaryDirectory())\(title).pdf"
pdfData.write(toFile: path, atomically: true)
print("open \(path)") // check if we got the path right.
// open share dialog
print("opening share dialog")
// Initialize Document Interaction Controller
self.interactionController = UIDocumentInteractionController(url: URL(fileURLWithPath: path))
// Configure Document Interaction Controller
self.interactionController!.delegate = self
// Present Open In Menu
self.interactionController!.presentOptionsMenu(from: yourexportbarbuttonoutlet, animated: true) // create an outlet from an Export bar button outlet, then use it as the `from` argument
}
This can be called with
openPDF("Hello World", title: "HelloWorld")
to instantly create a pdf file and open the share dialog for it.
Edit: Found an interesting (though not polished) workaround to getting text to open up in Google Docs: use the function from the "creating a .txt
file" section here, and just change the filename to "\(title).docx"
. This will fool Docs into thinking it's a .docx
document, which will allow the text to open in Docs successfully. Unfortunately, this creates an invalid document that can't be opened by Pages, Word, or really any other app because it doesn't actually create a real document file. And the Interaction Controller will make it look to the user like they can also open it in Pages, though that invariably fails.