ビューを画像にレンダリングする方法はありますか?スクリーンショットと同じですが、そのメソッドに任意のビューを指定できます。私はiOSでそれを行う方法を知っています。ビューコンテンツを保存していますが、Mac OSでそれを行うにはどうすればよいですか?
3 に答える
いくつかの方法がありますが、どれも完璧に機能しません。多くの問題は、レイヤーバックビューに関連しています。
レイヤーバッキングまたはホスティングビューがない場合は、次のコードを使用できます。
NSData* data = [mainView dataWithPDFInsideRect:[mainView bounds]];
NSImage *img = [[NSImage alloc] initWithData:data];
レイヤーベースのビューを使用する場合:
10.8まで私にとって最良の方法は
NSSize mySize = mapImage.bounds.size;
NSSize imgSize = NSMakeSize( mySize.width, mySize.height );
NSBitmapImageRep *bir = [mapImage bitmapImageRepForCachingDisplayInRect:[mapImage bounds]];
[bir setSize:imgSize];
[mapImage cacheDisplayInRect:[mapImage bounds] toBitmapImageRep:bir];
caheImg = [[NSImage alloc]initWithSize:imgSize];
[caheImg addRepresentation:bir];
しかし、10.8bitmapImageRepForCachingDisplayInRect
で、レイヤーバックビューの操作を停止しました。
画面のスクリーンショットを作成してビューを切り取るオプションがあります。
+ (NSImage*) screenCacheImageForView:(NSView*)aView
{
NSRect originRect = [aView convertRect:[aView bounds] toView:[[aView window] contentView]];
NSRect rect = originRect;
rect.origin.y = 0;
rect.origin.x += [aView window].frame.origin.x;
rect.origin.y += [[aView window] screen].frame.size.height - [aView window].frame.origin.y - [aView window].frame.size.height;
rect.origin.y += [aView window].frame.size.height - originRect.origin.y - originRect.size.height;
CGImageRef cgimg = CGWindowListCreateImage(rect,
kCGWindowListOptionIncludingWindow,
(CGWindowID)[[aView window] windowNumber],
kCGWindowImageDefault);
return [[NSImage alloc] initWithCGImage:cgimg size:[aView bounds].size];
}
私は自分のアプリでこのコードを使用していますが、これはうまく機能します。
ただし、アプリをセカンダリモニターにドラッグすると、スクリーンキャプチャがスローされ、間違ったrectがキャプチャされます。
次のコードは、将来誰かがこれに遭遇した場合に備えて、その問題を修正します(フィールドが減算されてから加算される計算から冗長な計算もいくつか削除しました)。
NSRect originRect = [aView convertRect:[aView bounds] toView:[[aView window] contentView]];
NSArray *screens = [NSScreen screens];
NSScreen *primaryScreen = [screens objectAtIndex:0];
NSRect rect = originRect;
rect.origin.y = 0;
rect.origin.x += [aView window].frame.origin.x;
rect.origin.y = primaryScreen.frame.size.height - [aView window].frame.origin.y - originRect.origin.y - originRect.size.height;
@Remizorrからの回答は、macOS HighSierra10.13.4でも説明されているようにObjectiveCで機能します。-Xcode9.2。
これは、layerBackedビュー(wantsLayer = true
)でも機能します。
更新されたSwiftバージョンは次のとおりです。
extension NSView {
func snapshotImage() -> NSImage? {
guard let window = window,
let screen = window.screen,
let contentView = window.contentView else { return nil }
let originRect = self.convert(self.bounds, to:contentView)
var rect = originRect
rect.origin.x += window.frame.origin.x
rect.origin.y = 0
rect.origin.y += screen.frame.size.height - window.frame.origin.y - window.frame.size.height
rect.origin.y += window.frame.size.height - originRect.origin.y - originRect.size.height
guard window.windowNumber > 0 else { return nil }
guard let cgImage = CGWindowListCreateImage(rect, .optionIncludingWindow, CGWindowID(window.windowNumber), CGWindowImageOption.bestResolution) else { return nil }
return NSImage(cgImage: cgImage, size: self.bounds.size)
}
}
注:これはWKWebViewでも機能し、再生中のWKWebViewビデオのスナップショットを取得します(WKWebViews takeSnapshotは取得しません);)。