0

I tried to save custom UIView to pdf in my swift app, but I failed.

So I try to use same way with OC, it is working fine, but not with swift.

These is my test code with swift and OC, both of them can display same block in simulator and device.

swift:

@objc class TestViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let sub = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
        sub.backgroundColor = .red
        view.addSubview(sub)

        let data = NSMutableData()
        UIGraphicsBeginPDFContextToData(data, view.bounds, nil)
        UIGraphicsBeginPDFPage()
        view.layer.draw(in: UIGraphicsGetCurrentContext()!)
        UIGraphicsEndPDFContext()

        let path = NSTemporaryDirectory() + "/pdftest_s.pdf"
        data.write(toFile: path, atomically: true)
        print(path)
    }
}

OC:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
@end

@implementation ViewController
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIView *sub = [UIView.alloc initWithFrame:CGRectMake(10, 10, 100, 100)];
    sub.backgroundColor = UIColor.redColor;
    [self.view addSubview:sub];

    NSMutableData *data = [NSMutableData data];
    UIGraphicsBeginPDFContextToData(data, self.view.bounds, nil);
    UIGraphicsBeginPDFPage();
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIGraphicsEndPDFContext();

    NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"pdftest.pdf"];
    [data writeToFile:path atomically:YES];
    NSLog(@"%@", path);
}
@end

In both Xcode 8.3 and 9.0 beta6 OC is working fine, but not with swift (3 and 4).

I was trying to use UIPrintPageRenderer, it is not working!

amish
  • 335
  • 4
  • 17
Shawn Clovie
  • 38
  • 1
  • 5

3 Answers3

1

In Obj code you are rendering view.layer

[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

while in swift code you forgot to do so

replace view.layer.draw(in: UIGraphicsGetCurrentContext()!) with rendering

Hope it is helpful

Prashant Tukadiya
  • 15,838
  • 4
  • 62
  • 98
1

Updated code in Swift 4.2:

Use below UIView Extension to easily create PDF from UIView.

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 ""
    }
  }
}

Credit: http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/

Ashish Chauhan
  • 1,316
  • 15
  • 22
0

You need to render your view in your current Graphics Context. in swift3 you can do it as

view.layer.render(in: UIGraphicsGetCurrentContext()!)

As per Apple documentation

renderInContext: Renders the layer and its sublayers into the specified context.

luckyShubhra
  • 2,731
  • 1
  • 12
  • 19