I am trying to capture the image that the webview is displaying to the user, so I can some color analysis of the web page. When I try to get the image from it\'s parent, I am ba
You will need to have access to a target writeable place - the snapshotURL ie.., such as the desktop, so we provide a handler for that:
func registerSnaphotsURL(_ sender: NSMenuItem, handler: @escaping (URL) -> Void) {
var targetURL : URL
// 1st around authenticate and cache sandbox data if needed
if isSandboxed, desktopData == nil {
targetURL =
UserSettings.SnapshotsURL.value.count == 0
? getDesktopDirectory()
: URL.init(fileURLWithPath: UserSettings.SnapshotsURL.value, isDirectory: true)
let openPanel = NSOpenPanel()
openPanel.message = "Authorize access to "
openPanel.prompt = "Authorize"
openPanel.canChooseFiles = false
openPanel.canChooseDirectories = true
openPanel.canCreateDirectories = true
openPanel.directoryURL = targetURL
openPanel.begin() { (result) -> Void in
if (result == .OK) {
targetURL = openPanel.url!
// Since we do not have data, clear any bookmark
if self.storeBookmark(url: targetURL, options: self.rwOptions) {
self.desktopData = self.bookmarks[targetURL]
UserSettings.SnapshotsURL.value = targetURL.absoluteString
if !self.saveBookmarks() {
print("Yoink, unable to save snapshot bookmark")
}
self.desktopData = self.bookmarks[targetURL]
handler(targetURL)
}
}
else
{
return
}
}
}
else
{
targetURL =
UserSettings.SnapshotsURL.value.count == 0
? getDesktopDirectory()
: URL.init(fileURLWithPath: UserSettings.SnapshotsURL.value, isDirectory: true)
handler(targetURL)
}
}
we wanted to allow single (view controller) and all current views (app delegate) so two actions in their respective files, both making use of the register handler.
App Delegate
@objc @IBAction func snapshotAllPress(_ sender: NSMenuItem) {
registerSnaphotsURL(sender) { (snapshotURL) in
// If we have a return object just call them, else notify all
if let wvc : WebViewController = sender.representedObject as? WebViewController {
sender.representedObject = snapshotURL
wvc.snapshot(sender)
}
else
{
sender.representedObject = snapshotURL
let notif = Notification(name: Notification.Name(rawValue: "SnapshotAll"), object: sender)
NotificationCenter.default.post(notif)
}
}
}
View Controller
func viewDidLoad() {
NotificationCenter.default.addObserver(
self,
selector: #selector(WebViewController.snapshotAll(_:)),
name: NSNotification.Name(rawValue: "SnapshotAll"),
object: nil)
}
@objc func snapshotAll(_ note: Notification) {
snapshot(note.object as! NSMenuItem)
}
view singleton action
@objc @IBAction func snapshotPress(_ sender: NSMenuItem) {
guard let url = webView.url, url != webView.homeURL else { return }
guard let snapshotURL = sender.representedObject as? URL else {
// Dispatch to app delegate to handle a singleton
sender.representedObject = self
appDelegate.snapshotAllPress(sender)
return
}
sender.representedObject = snapshotURL
snapshot(sender)
}
the webView interaction to capture an image
@objc func snapshot(_ sender: NSMenuItem) {
guard let url = webView.url, url != webView.homeURL else { return }
guard var snapshotURL = sender.representedObject as? URL else { return }
// URL has only destination, so add name and extension
let filename = String(format: "%@ Shapshot at %@",
(url.lastPathComponent as NSString).deletingPathExtension,
String.prettyStamp())
snapshotURL.appendPathComponent(filename)
snapshotURL = snapshotURL.appendingPathExtension("png")
webView.takeSnapshot(with: nil) { image, error in
if let image = image {
self.webImageView.image = image
DispatchQueue.main.async {
self.processSnapshotImage(image, to: snapshotURL)
}
}
else
{
self.userAlertMessage("Failed taking snapshot", info: error?.localizedDescription)
self.webImageView.image = nil
}
}
}
and the capture to the targeted area
func processSnapshotImage(_ image: NSImage, to snapshotURL: URL) {
guard let tiffData = image.tiffRepresentation else { NSSound(named: "Sosumi")?.play(); return }
let bitmapImageRep = NSBitmapImageRep(data: tiffData)
do
{
try bitmapImageRep?.representation(using: .png, properties: [:])?.write(to: snapshotURL)
// https://developer.apple.com/library/archive/qa/qa1913/_index.html
if let asset = NSDataAsset(name:"Grab") {
do {
// Use NSDataAsset's data property to access the audio file stored in Sound.
let player = try AVAudioPlayer(data:asset.data, fileTypeHint:"caf")
// Play the above sound file.
player.play()
} catch {
print("no sound for you")
}
}
if snapshotURL.hideFileExtensionInPath(), let name = snapshotURL.lastPathComponent.removingPercentEncoding {
print("snapshot => \(name)")
}
} catch let error {
appDelegate.userAlertMessage("Snapshot failed", info: error.localizedDescription)
}
}