在命令行中使用WebView:在展开时发现nil错误

时间:2017-06-18 19:17:41

标签: swift macos cocoa webview

我有一个Cocoa App,它使用WebView加载一些页面并截取屏幕截图。

可可应用代码:

class ViewController: NSViewController, WebFrameLoadDelegate {

    @IBOutlet var web: WebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        web.frame = NSRect(x: 0, y: 0, width: 1024, height: 768)
        web.preferences.isJavaScriptEnabled = true
        web.preferences.isJavaEnabled = true
        web.preferences.arePlugInsEnabled = true
        web.frameLoadDelegate = self
        web.mainFrame.load(URLRequest(url: URL(string: "https://google.com")!))
        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {

        let queue = DispatchQueue(label: "pic")
        let delay: DispatchTimeInterval = .seconds(2)
        queue.asyncAfter(deadline: .now() + delay, execute: {
            let data = self.web.layer?.data() // data() is a extension on CALayer
            let nd = NSData(data: data!)
            nd.write(toFile: "/Users/mac/Desktop/screenshot.png", atomically: true)
        })
    }
}

它工作正常,我得到了网页的截图。

现在,我想过在命令行而不是Cocoa App中做这件事。

命令行代码:

class Main1: NSObject, WebFrameLoadDelegate
{
    var web: WebView!
    override init()
    {
        super.init()
        web = WebView(frame: CGRect(x: 0, y: 0, width: 1024, height: 768))
        web.preferences.isJavaScriptEnabled = true
        web.preferences.isJavaEnabled = true
        web.preferences.arePlugInsEnabled = true
        web.frameLoadDelegate = self
        web.shouldUpdateWhileOffscreen = true
        web.mainFrame.load(URLRequest(url: URL(string: "https://google.com")!))
    }

    func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!)
    {

        let queue = DispatchQueue(label: "pic")
        let delay: DispatchTimeInterval = .seconds(2)
        queue.asyncAfter(deadline: .now() + delay, execute: {
            let data = self.web.layer?.data()
            let nd = NSData(data: data!) // <-- The data is nil error
            nd.write(toFile: "/Users/mac/Desktop/screenshot.png", atomically: true)
        })
    }
}

extension CALayer {

/// Get `Data` representation of the layer.
///
/// - Parameters:
///   - fileType: The format of file. Defaults to PNG.
///   - properties: A dictionary that contains key-value pairs specifying image properties.
///
/// - Returns: `Data` for image.

func data(using fileType: NSBitmapImageFileType = .PNG, properties: [String : Any] = [:]) -> Data {
    let width = Int(bounds.width * self.contentsScale)
    let height = Int(bounds.height * self.contentsScale)
    let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)!
    imageRepresentation.size = bounds.size

    let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!

    render(in: context.cgContext)

    return imageRepresentation.representation(using: fileType, properties: properties)!
}

}

let m = Main1()
RunLoop.main.run()

我正在fatal error: unexpectedly found nil while unwrapping an Optional value

为什么我不能在命令行中使用相同的代码?可能是什么原因?

如何解决?

谢谢!

P.S。 CALayer的扩展名取自here

1 个答案:

答案 0 :(得分:1)

我在我的机器上尝试了命令行代码。

你几乎得到了它。

只需添加web.wantsLayer = true即可获得屏幕截图而非错误: - )

提示:与phantomJS相比,它会创建非常大的图像。如果可能的话,尽量减小图像尺寸。