WKWebViewにHTML表示させ、PDF化する（Swift2.2, XCode7.3.1）

業務でHTMLファイルをPDF化する必要があったのでメモしておきます。

#画面
<img width="432" alt="スクリーンショット 2016-05-19 12.22.14.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/40894/26863774-8dc8-b1a0-2103-90d0a04efd03.jpeg">
<img width="432" alt="スクリーンショット 2016-05-19 12.22.26.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/40894/e31ab84c-03f0-00cc-e82c-2f62508fe990.jpeg">


#コード
```swift
import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate {
    private var subView: UIView!
    private var webView: WKWebView!
    
    override func viewDidLoad()
    {
        super.viewDidLoad()

        let size = view.frame.size
        subView = UIView(frame: CGRectMake(0, 0, size.width, size.height - 50))
        
        let btn = UIButton(type: .System)
        btn.frame = CGRectMake(0, size.height - 50, 90, 40)
        btn.setTitle("set HTML", forState: .Normal)
        btn.addTarget(self, action: #selector(ViewController.tapBtn(_:)), forControlEvents: .TouchUpInside)
        
        let btn2 = UIButton(type: .System)
        btn2.frame = CGRectMake(size.width * 0.35, size.height - 50, 90, 40)
        btn2.setTitle("set from web", forState: .Normal)
        btn2.addTarget(self, action: #selector(ViewController.tapBtn2(_:)), forControlEvents: .TouchUpInside)
        
        let btn3 = UIButton(type: .System)
        btn3.frame = CGRectMake(size.width * 0.7, size.height - 50, 90, 40)
        btn3.setTitle("create pdf", forState: .Normal)
        btn3.addTarget(self, action: #selector(ViewController.tapBtn3(_:)), forControlEvents: .TouchUpInside)
        
        view.addSubview(subView)
        view.addSubview(btn)
        view.addSubview(btn2)
        view.addSubview(btn3)
        
        webView = WKWebView()
        setupSubViews(subView)
    }

    internal func tapBtn(sender: UIButton) {
//        webView.loadHTMLString(getStrFromFile("test.html"), baseURL: nil)
        webView.loadHTMLString("hoge<br>piyo<br>foo<br>bar<br>hogeeeeeeeeeeeeeeeee", baseURL: nil)
    }
    
    internal func tapBtn2(sender: UIButton) {
        let req = NSURLRequest(URL: NSURL(string:"http://www.yahoo.co.jp/")!)
        webView.loadRequest(req)
    }
    
    internal func tapBtn3(sender: UIButton) {
        let path = NSHomeDirectory().stringByAppendingString("/hoge.pdf")
        PDFMaker.make([webView], path: path)
    }
    
    
    private func setupSubViews(v: UIView)
    {
//        webView.navigationDelegate = self
//        webView.scrollView.delegate = self
        webView.translatesAutoresizingMaskIntoConstraints = false
        v.addSubview(webView)
        var viewBindingsDict = [String: AnyObject]()
        viewBindingsDict["webView"] = webView
        v.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewBindingsDict))
        v.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewBindingsDict))
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // プロジェクトに追加したローカルファイルの文字列取得
    private func getStrFromFile(fname: String) -> String {
        var ret = ""
        var path = NSString(string: fname)
        // Encode 日本語ファイル対応
        path = path.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
        let ext = path.pathExtension
        let filename = path.stringByDeletingPathExtension
        do {
            if let path = NSBundle.mainBundle().pathForResource(filename, ofType: ext) {
                ret = try String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
            }
        } catch {
            print("error getStrFromFile")
        }
        return ret
    }
}

// PDF作成クラス
class PDFMaker {
    private class func renderViews(views: [UIView]) {
        guard let context = UIGraphicsGetCurrentContext() else {
            return
        }
        views.forEach {
            if let scrollView = $0 as? UIScrollView {
                let tmpInfo = (offset: scrollView.contentOffset, frame: scrollView.frame)
                scrollView.contentOffset = CGPointZero
                scrollView.frame = CGRect(origin: CGPointZero, size: scrollView.contentSize)
                UIGraphicsBeginPDFPageWithInfo(scrollView.frame, nil)
                $0.layer.renderInContext(context)
                scrollView.frame = tmpInfo.frame
                scrollView.contentOffset = tmpInfo.offset
            } else {
                UIGraphicsBeginPDFPageWithInfo($0.bounds, nil)
                $0.layer.renderInContext(context)
            }
        }
    }
    
    class func make(views: [UIView], path: String) {
        UIGraphicsBeginPDFContextToFile(path, CGRectZero, nil)
        renderViews(views)
        UIGraphicsEndPDFContext()
    }
    
    class func make(views: [UIView]) -> NSData {
        let data = NSMutableData()
        UIGraphicsBeginPDFContextToData(data, CGRectZero, nil)
        renderViews(views)
        UIGraphicsEndPDFContext()
        return data
    }
}
```

#作成したPDFを探す
シミュレータの場合

```shell-session
➜  ~ find ~/Library/Developer/CoreSimulator/Devices -name "hoge.pdf"
```