una pantalla mini hacer cómo como captura apple ios objective-c uiview screenshot

ios - mini - ¿Cómo tomo una captura de pantalla de un UIView?



cómo hacer una captura de pantalla en iphone 5 (14)

Me pregunto cómo mi aplicación de iPhone puede tomar una captura de pantalla de un UIView específico como un UIImage .

Intenté este código pero todo lo que obtengo es una imagen en blanco.

UIGraphicsBeginImageContext(CGSizeMake(320,480)); CGContextRef context = UIGraphicsGetCurrentContext(); [myUIView.layer drawInContext:context]; UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

myUIView tiene dimensiones de 320x480 y tiene algunas sub-vistas. ¿Cuál es la forma correcta de hacer esto?


Detalles

xCode 8.2.1, Swift 3

Captura de pantalla de UIView en Swift

import UIKit extension UIView { var screenShot: UIImage? { UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1.0); if let _ = UIGraphicsGetCurrentContext() { drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } }

Uso

screenShotRenderer.image = viewForScreenShot.screenShot

Ejemplo completo del uso

Controlador de vista con extensión UIView

import UIKit class ViewController: UIViewController { @IBOutlet var viewForScreenShot: UIView! @IBOutlet var screenShotRenderer: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } @IBAction func makeViewScreenShotButtonTapped2(_ sender: UIButton) { screenShotRenderer.image = viewForScreenShot.screenShot } } extension UIView { var screenShot: UIImage? { UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1.0); if let _ = UIGraphicsGetCurrentContext() { drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } }

Main.storyboard

<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="_2214957" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Acg-GO-mMN"> <rect key="frame" x="67" y="28" width="240" height="128"/> <subviews> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="4Fr-O3-56t"> <rect key="frame" x="72" y="49" width="96" height="30"/> <constraints> <constraint firstAttribute="height" constant="30" id="cLv-es-h7Q"/> <constraint firstAttribute="width" constant="96" id="ytF-FH-gdm"/> </constraints> <nil key="textColor"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> </subviews> <color key="backgroundColor" red="0.0" green="0.47843137250000001" blue="1" alpha="0.49277611300000002" colorSpace="custom" customColorSpace="sRGB"/> <color key="tintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/> <constraints> <constraint firstItem="4Fr-O3-56t" firstAttribute="centerX" secondItem="Acg-GO-mMN" secondAttribute="centerX" id="egj-rT-Gz5"/> <constraint firstItem="4Fr-O3-56t" firstAttribute="centerY" secondItem="Acg-GO-mMN" secondAttribute="centerY" id="ymi-Ll-WIV"/> </constraints> </view> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SQq-IE-pvj"> <rect key="frame" x="109" y="214" width="157" height="30"/> <state key="normal" title="make view screen shot"/> <connections> <action selector="makeViewScreenShotButtonTapped2:" destination="BYZ-38-t0r" eventType="touchUpInside" id="KSY-ec-uvA"/> </connections> </button> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CEZ-Ju-Tpq"> <rect key="frame" x="67" y="269" width="240" height="128"/> <constraints> <constraint firstAttribute="width" constant="240" id="STo-iJ-rM4"/> <constraint firstAttribute="height" constant="128" id="tfi-zF-zdn"/> </constraints> </imageView> </subviews> <color key="backgroundColor" red="0.95941069162436543" green="0.95941069162436543" blue="0.95941069162436543" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="CEZ-Ju-Tpq" firstAttribute="top" secondItem="SQq-IE-pvj" secondAttribute="bottom" constant="25" id="6x1-iB-gKF"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="leading" secondItem="CEZ-Ju-Tpq" secondAttribute="leading" id="LUp-Be-FiC"/> <constraint firstItem="SQq-IE-pvj" firstAttribute="top" secondItem="Acg-GO-mMN" secondAttribute="bottom" constant="58" id="Qu0-YT-k9O"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="Qze-zd-ajY"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="trailing" secondItem="CEZ-Ju-Tpq" secondAttribute="trailing" id="b1d-sp-GHD"/> <constraint firstItem="SQq-IE-pvj" firstAttribute="centerX" secondItem="CEZ-Ju-Tpq" secondAttribute="centerX" id="qCL-AF-Cro"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="8" symbolic="YES" id="u5Y-eh-oSG"/> <constraint firstItem="CEZ-Ju-Tpq" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="vkx-JQ-pOF"/> </constraints> </view> <connections> <outlet property="screenShotRenderer" destination="CEZ-Ju-Tpq" id="8QB-OE-ib6"/> <outlet property="viewForScreenShot" destination="Acg-GO-mMN" id="jgL-yn-8kk"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="32.799999999999997" y="37.331334332833585"/> </scene> </scenes> </document>

Resultado



Creé esta extensión para guardar una captura de pantalla de UIView

extension UIView { func saveImageFromView(path path:String) { UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale) drawViewHierarchyInRect(bounds, afterScreenUpdates: true) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() UIImageJPEGRepresentation(image, 0.4)?.writeToFile(path, atomically: true) }}

llamar :

let pathDocuments = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).first! let pathImage = "/(pathDocuments)//(user!.usuarioID.integerValue).jpg" reportView.saveImageFromView(path: pathImage)

Si desea crear un png debe cambiar:

UIImageJPEGRepresentation(image, 0.4)?.writeToFile(path, atomically: true)

por

UIImagePNGRepresentation(image)?.writeToFile(path, atomically: true)


Creo que puede querer renderInContext , no drawInContext . drawInContext es más un método que anularías ...

Tenga en cuenta que puede que no funcione en todas las vistas, específicamente hace un año o algo así, cuando traté de usar esto con la vista de cámara en vivo, no funcionó.


Debe capturar la ventana clave para una captura de pantalla o una UIView. Puede hacerlo en Resolución Retina usando UIGraphicsBeginImageContextWithOptions y establecer su parámetro de escala 0.0f. Siempre captura en resolución nativa (retina para iPhone 4 y posterior).

Este hace una captura de pantalla de pantalla completa (ventana clave)

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; CGRect rect = [keyWindow bounds]; UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f); CGContextRef context = UIGraphicsGetCurrentContext(); [keyWindow.layer renderInContext:context]; UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

Este código captura una UIView en resolución nativa

CGRect rect = [captureView bounds]; UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f); CGContextRef context = UIGraphicsGetCurrentContext(); [captureView.layer renderInContext:context]; UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

Esto ahorra el UIImage en formato jpg con un 95% de calidad en la carpeta de documentos de la aplicación si necesita hacerlo.

NSString *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/capturedImage.jpg"]]; [UIImageJPEGRepresentation(capturedImage, 0.95) writeToFile:imagePath atomically:YES];


El siguiente fragmento se usa para tomar una captura de pantalla:

UIGraphicsBeginImageContext(self.muUIView.bounds.size); [myUIView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

Utilice el método renderInContext: lugar de drawInContext: method

renderInContext: method representa el receptor y sus subcapas en el contexto actual. Este método se representa directamente desde el árbol de capas.


Hay una nueva API de iOS 10

extension UIView { func makeScreenshot() -> UIImage { let renderer = UIGraphicsImageRenderer(bounds: self.bounds) return renderer.image { (context) in self.layer.render(in: context.cgContext) } } }


He creado una extensión utilizable para que UIView tome una captura de pantalla en Swift:

extension UIView{ var screenshot: UIImage{ UIGraphicsBeginImageContext(self.bounds.size); let context = UIGraphicsGetCurrentContext(); self.layer.renderInContext(context) let screenShot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return screenShot } }

Para usarlo solo escribe:

let screenshot = view.screenshot


iOS 7 tiene un nuevo método que le permite dibujar una jerarquía de vista en el contexto gráfico actual. Esto se puede usar para obtener un UIImage muy rápido.

Implementé un método de categoría en UIView para obtener la vista como un UIImage :

- (UIImage *)pb_takeSnapshot { UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale); [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }

Es considerablemente más rápido que el método renderInContext:

Referencia: https://developer.apple.com/library/content/qa/qa1817/_index.html

ACTUALIZAR PARA SWIFT : una extensión que hace lo mismo:

extension UIView { func pb_takeSnapshot() -> UIImage { UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale) drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true) // old style: layer.renderInContext(UIGraphicsGetCurrentContext()) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } }

ACTUALIZACIÓN PARA SWIFT 3

UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale) drawHierarchy(in: self.bounds, afterScreenUpdates: true) let image = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return image



puede usar la siguiente categoría de UIView -

@implementation UIView (SnapShot) - (UIImage *)snapshotImage { UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale); [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO]; // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } @end


- (void)drawRect:(CGRect)rect { UIGraphicsBeginImageContext(self.bounds.size); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil); }

Este método puede poner en su clase de controlador.


-(UIImage *)convertViewToImage { UIGraphicsBeginImageContext(self.bounds.size); [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }


CGImageRef UIGetScreenImage();

Apple ahora nos permite usarlo en una aplicación pública, a pesar de que es una API privada