let user save pdf outside app in IOS swift

前端 未结 1 1372
不知归路
不知归路 2021-01-24 08:19

I Made a PDF an save it in my App, but I want let de user save the PDF document in a directory outside of my app. (Sorry for bad English, I am from Swiss.)

The markupTex

相关标签:
1条回答
  • 2021-01-24 08:56

    I am finish, that is my code

    func SavePdfUser(){

        // Create page rect
        let pageRect = CGRect(x: 0, y: 0, width: 595.28, height: 841.89) // A4, 72 dpi
    
        // Create PDF context and draw
        let pdfData = NSMutableData()
    
        UIGraphicsBeginPDFContextToData(pdfData, pageRect, nil)
        UIGraphicsBeginPDFPage()
    
        // From here you can draw page, best make it in a function
        PdfErstellung.PdfErstellen(auswahlZeilen, vitalstoffWerteListe, heuteString)
    
        UIGraphicsEndPDFContext()
    
        // Save pdf DATA through user
        let activityViewController = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)
        activityViewController.popoverPresentationController?.sourceView = self.view // für IPAD nötig
        self.present(activityViewController, animated: true, completion: nil)
    
        // save temporary for preview 
        let dateiName = "Vitalstoffwerte " + heuteString
        let fileUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(dateiName).pdf")
    
        do {
            try pdfData.write(to: fileUrl, options: .atomic)
        } catch {
            print(error,"file not save")
        }
    
        // Preview
        let webview = WKWebView(frame: UIScreen.main.bounds)
        view.addSubview(webview)
        webview.load(URLRequest(url: fileUrl))
    }
    

    import UIKit import Foundation

    class PdfErstellung {

    static func PdfErstellen(_ auswahlZeilen : [LebensmittelDataTV], _ vitalstoffWerteListe : [LebensmittelDataTV], _ heuteString : String) {
    
        var y = 0 // Points from above - von oben
        var x = 0 // Points form left - von links
        var width = 0 // length of rect - länge vom rechteck
        var height = 0 // height of rect - höhe vom rechteck
        var stringRechteck = CGRect(x: x, y: y, width: width, height: height) // make rect for text - rechteck für Text
    
        var paragraphStyle = NSMutableParagraphStyle() // text alignment - text ausrichtung
    
        var font = UIFont(name: "HelveticaNeue-Bold", size: 10.0) // Important: the font name must be written correct - Wichtig: Textname muss korrekt geschrieben werden
        var text = ""
    
        let attributes = [
            NSAttributedString.Key.paragraphStyle: paragraphStyle,
            NSAttributedString.Key.font: font,
            NSAttributedString.Key.foregroundColor: UIColor.black
        ]
    
        // Title - ÜBERSCHRIFT
    
        font = UIFont(name: "HelveticaNeue-Bold", size: 20.0)
        text = "Tagesbedarf in % vom " + heuteString // heuteString = date/datum
        paragraphStyle.alignment = .left
        x = 50; y = 30; width = 300; height = 40
        stringRechteck = CGRect(x: x, y: y, width: width, height: height)
        text.draw(in: stringRechteck, withAttributes: attributes)
    
    
        // List - Vitalstoffwerte Liste
    
        y = 45
    
        for zeile in 0..<vitalstoffWerteListe.count {
    
            let druckenVitalstoffWerte = vitalstoffWerteListe[zeile]
    
            if druckenVitalstoffWerte.zeilenInfoID == 0 { // Title - Überschrift
    
                y = y + 5 // distance to above becaus is title - Abstand nach oben, weil Überschrift
                x = 50; width = 80; height = 20
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                font = UIFont(name: "HelveticaNeue-Bold", size: 10.0) // change font - verändere schrift
                text = druckenVitalstoffWerte.name
                text.draw(in: stringRechteck, withAttributes: attributes)
                font = UIFont(name: "HelveticaNeue", size: 8.0) // change font back - schrift zurück ändern
    
            } else { // or detail
    
                x = 50; width = 90; height = 20
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                text = druckenVitalstoffWerte.name
                text.draw(in: stringRechteck, withAttributes: attributes)
    
                x = 150; width = 40
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                text = druckenVitalstoffWerte.anzahl
                paragraphStyle.alignment = .right
                text.draw(in: stringRechteck, withAttributes: attributes)
                paragraphStyle.alignment = .left
    
                x = 195; width = 20
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                text = druckenVitalstoffWerte.masse
                text.draw(in: stringRechteck, withAttributes: attributes)
    
            }
            y = y + 10 // 10 down for next line - 10 nach unten für nächste Zeile
        }
    
        // Title - Überschrift
    
        x = 220; y = 50; width = 100; height = 20
        text = "Lebensmittel"
        font = UIFont(name: "HelveticaNeue-Bold", size: 8.0)
        paragraphStyle.alignment = .left
        stringRechteck = CGRect(x: x, y: y, width: width, height: height)
        text.draw(in: stringRechteck, withAttributes: attributes)
        font = UIFont(name: "HelveticaNeue", size: 8.0)
    
        // List - Lebensmittelliste
    
        y = 60
    
        for zeile in 0..<auswahlZeilen.count {
    
            let auswahlZeilenObjekt = auswahlZeilen[zeile]
    
            x = 220; width = 90; height = 20
            stringRechteck = CGRect(x: x, y: y, width: width, height: height)
            text = auswahlZeilenObjekt.name
            text.draw(in: stringRechteck, withAttributes: attributes)
    
            x = 320; width = 40
            stringRechteck = CGRect(x: x, y: y, width: width, height: height)
            text = auswahlZeilenObjekt.anzahl
            paragraphStyle.alignment = .right
            text.draw(in: stringRechteck, withAttributes: attributes)
            paragraphStyle.alignment = .left
    
            x = 365; width = 20
            stringRechteck = CGRect(x: x, y: y, width: width, height: height)
            text = auswahlZeilenObjekt.masse
            text.draw(in: stringRechteck, withAttributes: attributes)
    
            y = y + 10
    
            if zeile == 75 { // 76 items - Zeilen
                break
            }
        }
    
        y = 60
    
         if auswahlZeilen.count > 75 { // new
    
            for zeile in 76..<auswahlZeilen.count {
    
                let auswahlZeilenObjekt = auswahlZeilen[zeile]
    
                x = 390; width = 90; height = 20
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                text = auswahlZeilenObjekt.name
                text.draw(in: stringRechteck, withAttributes: attributes)
    
                x = 490; width = 40
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                text = auswahlZeilenObjekt.anzahl
                paragraphStyle.alignment = .right
                text.draw(in: stringRechteck, withAttributes: attributes)
                paragraphStyle.alignment = .left
    
                x = 535; width = 20
                stringRechteck = CGRect(x: x, y: y, width: width, height: height)
                text = auswahlZeilenObjekt.masse
                text.draw(in: stringRechteck, withAttributes: attributes)
    
                y = y + 10
    
                if zeile == 151 { // 76 items - Zeilen
                    break
                }
            }
        }
    }
    

    }

    -- EDIT -- The Problem ist only in IOS 12.

    I do not know why, but in some simulator: I can make the file, and give the URL to UIActivityViewController and I have my own filename and in other the URL fail, and I must give the pdfData directly.

    My idea: I Try first the URL and if this fail then I give the pdfData

    do {
            let dateiName = "Vitalstoffwerte " + heuteString
            let fileUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(dateiName).pdf")
    
            do {
                try pdfData.write(to: fileUrl, options: .atomic)
            } catch {
                print(error,"file not save")
            }
    
            let activityViewController = UIActivityViewController(activityItems: [fileUrl], applicationActivities: nil)
            activityViewController.popoverPresentationController?.sourceView = self.view // für IPAD nötig
            self.present(activityViewController, animated: true, completion: nil)
    
        } catch {
    
            let activityViewController = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)
            activityViewController.popoverPresentationController?.sourceView = self.view // für IPAD nötig
            self.present(activityViewController, animated: true, completion: nil)
        }
    

    My problem ist, how I can find out, the user could save the file or not (if he had try it), can I ask the after the error code in the log? the do, catch do not go.

    2018-09-25 15:36:55.787894+0200 Vitalstoffcontroller[8656:186334] [default] [ERROR] Failed to determine whether URL /Users/lukashedinger/Library/Developer/CoreSimulator/Devices/45A185C5-6DEA-4A52-B415-939758FB7F7E/data/Containers/Data/Application/2469BE4A-53B2-4545-B5D7-E64FBCDB383E/tmp/Vitalstoffwerte 25092018-25092018.pdf (n) is managed by a file provider 2018-09-25 15:36:56.312499+0200 Vitalstoffcontroller[8656:186334] [ShareSheet] cancelled request - error: The operation couldn’t be completed. Invalid argument

    -- EDIT --

    ma temporary solution is, in ios12 I give the data to UIActivityViewController , otherwise I save the data as file and give the url to UIActivityViewController.

         if #available(iOS 12.0, *) {
    
            let activityViewController = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)
            activityViewController.popoverPresentationController?.sourceView = self.view // für IPAD nötig
            self.present(activityViewController, animated: true, completion: nil)
    
        } else {
    
            let dateiName = "Vitalstoffwerte " + heuteString
            let fileUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(dateiName).pdf")
            do {
                try pdfData.write(to: fileUrl, options: .atomic)
            } catch {
                print(error,"file not save")
            }
            let activityViewController = UIActivityViewController(activityItems: [fileUrl], applicationActivities: nil)
            activityViewController.popoverPresentationController?.sourceView = self.view // für IPAD nötig
            self.present(activityViewController, animated: true, completion: nil)
        }
    
    0 讨论(0)
提交回复
热议问题