IOS के भीतर UIView को पीडीएफ में कैसे बदलें?


87

ऐप में पीडीएफ कैसे प्रदर्शित करें, इसके बारे में बहुत सारे संसाधन हैं UIView। अब मैं जो काम कर रहा हूं, उससे पीडीएफ बनाना है UIViews

उदाहरण के लिए, मेरे पास एक UIViewसाक्षात्कार है, जैसे कि पाठ्यपुस्तकें,, UILabelsऔर UIImagesइसलिए मैं अपने सभी साक्षात्कारों और उप-साक्षात्कारों सहित एक पीडीएफ में बड़े UIView को कैसे परिवर्तित कर सकता हूं ?

मैंने Apple के iOS संदर्भ की जाँच की है । हालाँकि, यह केवल एक पीडीएफ फाइल पर पाठ / छवि के टुकड़े लिखने की बात करता है।

मैं जिस समस्या का सामना कर रहा हूं वह यह है कि जिस सामग्री को मैं पीडीएफ में लिखना चाहता हूं वह बहुत कुछ है। अगर मैं उन्हें टुकड़ा द्वारा पीडीएफ टुकड़े पर लिखता हूं, तो यह बहुत बड़ा काम होने वाला है। इसलिए मैं UIViewsपीडीएफ या बिटमैप पर लिखने का तरीका ढूंढ रहा हूं ।

मैंने स्टैक ओवरफ्लो के भीतर अन्य क्यू / ए से कॉपी किए गए स्रोत कोड की कोशिश की है। लेकिन यह मुझे केवल UIViewसीमा आकार के साथ एक रिक्त पीडीएफ देता है ।

-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [NSMutableData data];

    // Points the pdf converter to the mutable data object and to the UIView to be converted
    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
    UIGraphicsBeginPDFPage();

    // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
    [aView drawRect:aView.bounds];

    // remove PDF rendering context
    UIGraphicsEndPDFContext();

    // Retrieves the document directories from the iOS device
    NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

    NSString* documentDirectory = [documentDirectories objectAtIndex:0];
    NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];

    // instructs the mutable data object to write its context to a file on disk
    [pdfData writeToFile:documentDirectoryFilename atomically:YES];
    NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}

जवाबों:


124

ध्यान दें कि निम्नलिखित विधि केवल दृश्य का एक बिटमैप बनाती है; यह वास्तविक टाइपोग्राफी नहीं बनाता है।

(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [NSMutableData data];

    // Points the pdf converter to the mutable data object and to the UIView to be converted
    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
    UIGraphicsBeginPDFPage();
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();


    // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData

    [aView.layer renderInContext:pdfContext];

    // remove PDF rendering context
    UIGraphicsEndPDFContext();

    // Retrieves the document directories from the iOS device
    NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

    NSString* documentDirectory = [documentDirectories objectAtIndex:0];
    NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];

    // instructs the mutable data object to write its context to a file on disk
    [pdfData writeToFile:documentDirectoryFilename atomically:YES];
    NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}

यह भी सुनिश्चित करें कि आप आयात करें: QuartzCore / QuartzCore.h


2
+1 यह सरल समाधान खोजने से पहले मैंने पीडीएफ पीढ़ी पर कई पोस्टों के माध्यम से जाना।
जेसन जॉर्ज

7
मैं ऐसा ही करना चाहता था और आपकी विधि ठीक काम करती है लेकिन इसकी गुणवत्ता बहुत कम है। क्या मैं कुछ भूल गया?
iamin

7
मुझे संदेह है कि गुणवत्ता बहुत कम है क्योंकि यह यूआईवीवाई ले रहा है और इसे एक रैस्टर में परिवर्तित कर रहा है, जहां पाठ और छवियों को रेंडर करने के अन्य तरीके सीधे पीडीएफ फाइल में उन्हें वैक्टर के रूप में संरक्षित करते हैं।
जोशदान

3
मैं इस विधि का पालन कर रहा हूं, लेकिन मैं एक खाली पीडीएफ उत्पन्न कर रहा हूं। क्या कोई मेरी मदद कर सकता है ?
राज

यह कमाल का काम करता है !!! चीयर्स !! एकमात्र समस्या जो मेरे पास है, वह सिर्फ एक पृष्ठ में पीडीएफ उत्पन्न करती है। मैं एक लंबी पीडीएफ फाइल रखने के बजाय पृष्ठों को अलग कैसे कर सकता हूं?
रुडी

25

इसके अतिरिक्त, अगर किसी को दिलचस्पी है, तो यहां स्विफ्ट 3 कोड है:

func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
{
    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
    UIGraphicsBeginPDFPage()

    guard let pdfContext = UIGraphicsGetCurrentContext() else { return }

    aView.layer.render(in: pdfContext)
    UIGraphicsEndPDFContext()

    if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
        let documentsFileName = documentDirectories + "/" + fileName
        debugPrint(documentsFileName)
        pdfData.write(toFile: documentsFileName, atomically: true)
    }
}

1
यह केवल FirstPage के लिए PDF बना रहा है! स्क्रोलव्यू के बारे में क्या?
सौरभ प्रजापति

बड़ा अच्छा सवाल! हालांकि, मैं पूछने वाला नहीं हूं। शायद एक और सवाल शुरू करें?
रेट्रोविस

मैं एक ही समस्या है तो @ सौरभ प्रजापति और मैंने एक सवाल
जोनास डेचलमैन

10

अगर किसी को दिलचस्पी है, तो यहां स्विफ्ट 2.1 कोड:

    func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
    {
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
        UIGraphicsBeginPDFPage()

        guard let pdfContext = UIGraphicsGetCurrentContext() else { return }

        aView.layer.renderInContext(pdfContext)
        UIGraphicsEndPDFContext()

        if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
            let documentsFileName = documentDirectories + "/" + fileName
            debugPrint(documentsFileName)
            pdfData.writeToFile(documentsFileName, atomically: true)
        }
    }

आपके गार्ड के बयान का अर्थ है UIGraphicsEndPDFContext () नहीं कहा जाता है - शायद पहले एक defer जोड़ें?
डेविड एच

@ डेविड धन्यवाद, डेविड, अच्छा विचार है! इसके अलावा, मुझे लगता है, वहाँ एक अच्छा विचार है completion: (success: Bool) -> ()गार्ड वापसी के मामलों के लिए एक पूरा ब्लॉक तरह
डेनिस Rumiantsev

1
कल मैंने एक बड़ी छवि में दृश्य को रेंडर करके एक उच्च रिज़ॉल्यूशन छवि का उत्पादन करने के लिए एक क्यू एंड ए पोस्ट किया, फिर छवि को दिलचस्पी से एक पीडीएफ में ड्रा करें: stackoverflow.com/a/35442187/1633251
डेविड एच

5

UIView से एक पीडीएफ बनाने का एक सुपर आसान तरीका UIView एक्सटेंशन का उपयोग करना है

स्विफ्ट 4.2

extension UIView {

  // Export pdf from Save pdf in drectory and return pdf file path
  func exportAsPdfFromView() -> String {

      let pdfPageFrame = self.bounds
      let pdfData = NSMutableData()
      UIGraphicsBeginPDFContextToData(pdfData, pdfPageFrame, nil)
      UIGraphicsBeginPDFPageWithInfo(pdfPageFrame, nil)
      guard let pdfContext = UIGraphicsGetCurrentContext() else { return "" }
      self.layer.render(in: pdfContext)
      UIGraphicsEndPDFContext()
      return self.saveViewPdf(data: pdfData)

  }

  // Save pdf file in document directory
  func saveViewPdf(data: NSMutableData) -> String {  
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let docDirectoryPath = paths[0]
    let pdfPath = docDirectoryPath.appendingPathComponent("viewPdf.pdf")
    if data.write(to: pdfPath, atomically: true) {
        return pdfPath.path
    } else {
        return ""
    }
  }
}

क्रेडिट: http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/


धन्यवाद, यह काम किया, एक सवाल है, इसलिए मेरे पास लंबा स्क्रॉल दृश्य है, लेकिन पीडीएफ फाइल केवल इसके एक हिस्से को दिखाती है, इसलिए आपके कोड को उदाहरण के लिए इसे ऊँचाई देने का एक तरीका है?
हुसैन एलबेहीर

@HusseinElbeheiry बस पीडीएफ उत्पन्न करने के लिए contentView का उपयोग करें। जब मैं एक स्क्रॉल दृश्य (UIScrollView) बनाता हूं, तो मैं निश्चित रूप से एक ContentView (UIView) बनाऊंगा और contentView को स्क्रॉलव्यू में डालूंगा, और मैं सभी बाद के तत्वों को contentView में जोड़ दूंगा। इस स्थिति में, पीडीएफ दस्तावेज़ बनाने के लिए contentView का उपयोग करना पर्याप्त है। contentView.exportAsPdfFromView
iAleksandr

3

स्विफ्ट 5 / आईओएस 12 के साथ, आप को जोड़ सकते हैं CALayerके render(in:)साथ विधि UIGraphicsPDFRenderers ' writePDF(to:withActions:)के लिए एक से एक पीडीएफ फाइल बनाने के लिए विधि UIViewउदाहरण।


निम्नलिखित खेल का मैदान नमूना कोड दिखाता है कि कैसे उपयोग करें render(in:)और writePDF(to:withActions:):

import UIKit
import PlaygroundSupport

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .orange
let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60))
subView.backgroundColor = .magenta
view.addSubview(subView)

let outputFileURL = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("MyPDF.pdf")
let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds)

do {
    try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in
        context.beginPage()
        view.layer.render(in: context.cgContext)
    })
} catch {
    print("Could not create PDF file: \(error)")
}

नोट: playgroundSharedDataDirectoryअपने प्लेग्राउंड में उपयोग करने के लिए , आपको सबसे पहले आपको "MacOS" दस्तावेज़ "फ़ोल्डर में" साझा प्लेग्राउंड डेटा "नामक एक फ़ोल्डर बनाने की आवश्यकता है।


UIViewControllerनीचे दिया उपवर्ग पूरा कार्यान्वयन किसी iOS एप्लिकेशन के लिए पिछले उदाहरण refactor करने के लिए एक संभव तरीका:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        view.backgroundColor = .orange
        let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60))
        subView.backgroundColor = .magenta
        view.addSubview(subView)

        createPDF(from: view)
    }

    func createPDF(from view: UIView) {
        let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let outputFileURL = documentDirectory.appendingPathComponent("MyPDF.pdf")
        print("URL:", outputFileURL) // When running on simulator, use the given path to retrieve the PDF file

        let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds)

        do {
            try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in
                context.beginPage()
                view.layer.render(in: context.cgContext)
            })
        } catch {
            print("Could not create PDF file: \(error)")
        }
    }

}

2

यह UIView से पीडीएफ जेनरेट करेगा और - (IBAction)PrintPDF:(id)senderस्क्रीन पर आपके बटन के लिए प्रिंट सी, ऑब्जेक्टिव सी अटैच होगा। #import <QuartzCore/QuartzCore.h>ढांचा जोड़ें

ज फाइल

    @interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate>

    {
    UIPrintInteractionController *printController;
    }

- (IBAction)PrintPDF:(id)sender;

एम फ़ाइल

-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename

{
    NSMutableData *pdfData = [NSMutableData data];

    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
    UIGraphicsBeginPDFPage();
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();


    [aView.layer renderInContext:pdfContext];
    UIGraphicsEndPDFContext();

    NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

    NSString* documentDirectory = [documentDirectories objectAtIndex:0];
    NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
    NSString *file = [documentDirectory stringByAppendingPathComponent:@"yourPDF.pdf"];
    NSURL *urlPdf = [NSURL fileURLWithPath: file];

    [pdfData writeToFile:documentDirectoryFilename atomically:YES];
    NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);

}


- (IBAction)PrintPDF:(id)sender
{
    [self createPDFfromUIView:self.view saveToDocumentsWithFileName:@"yourPDF.pdf"];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourPDF.pdf"];
    NSData *myData = [NSData dataWithContentsOfFile: path];

    UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
    if(pic && [UIPrintInteractionController canPrintData: myData] ) {

        pic.delegate = self;

        UIPrintInfo *printInfo = [UIPrintInfo printInfo];
        printInfo.outputType = UIPrintInfoOutputGeneral;
        printInfo.jobName = [path lastPathComponent];
        printInfo.duplex = UIPrintInfoDuplexLongEdge;
        pic.printInfo = printInfo;
        pic.showsPageRange = YES;
        pic.printingItem = myData;

        void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) {
            //self.content = nil;
            if(!completed && error){

                NSLog(@"Print Error: %@", error);
            }
        };

        [pic presentAnimated:YES completionHandler:completionHandler];

    }

}

-4

मुझे पता नहीं क्यों, लेकिन कैसिलिक का जवाब मुझे iOS6.1 पर खाली स्क्रीन देता है। नीचे दिया गया कोड काम करता है।

-(NSMutableData *)createPDFDatafromUIView:(UIView*)aView 
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [NSMutableData data];

    // Points the pdf converter to the mutable data object and to the UIView to be converted
    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
    UIGraphicsBeginPDFPage();
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();


    // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData

    [aView.layer renderInContext:pdfContext];

    // remove PDF rendering context
    UIGraphicsEndPDFContext();

    return pdfData;
}


-(NSString*)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [self createPDFDatafromUIView:aView];

    // Retrieves the document directories from the iOS device
    NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

    NSString* documentDirectory = [documentDirectories objectAtIndex:0];
    NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];

    // instructs the mutable data object to write its context to a file on disk
    [pdfData writeToFile:documentDirectoryFilename atomically:YES];
    NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
    return documentDirectoryFilename;
}

16
यह एक ही सटीक कोड है क्योंकि मेरा उत्तर सिर्फ दो अलग-अलग तरीकों से टूट गया है ???? जब आपको लगता है कि यह एक ही कोड है, तो यह आपकी रिक्त स्क्रीन समस्या कैसे तय करता है ??
कैसपिक

मेरा भी ऐसा ही अनुभव है। पहले कोड से एक खाली पीडीएफ मिला। एलेक्स के दो के रूप में इसे विभाजित करते हुए, इसने काम किया। क्यों नहीं समझा सकता।
टॉम तल्क सोलु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.