Как сделать снимок экрана UIView? - PullRequest
131 голосов
/ 07 февраля 2010

Мне интересно, как мое приложение для iPhone может сделать снимок экрана определенного UIView как UIImage.

Я попробовал этот код, но все, что я получил, это пустое изображение.

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

myUIView имеет размеры 320x480 и имеет несколько подвидов. Как правильно это сделать?

Ответы [ 15 ]

182 голосов
/ 21 сентября 2013

В iOS 7 появился новый метод, который позволяет рисовать иерархию представлений в текущем графическом контексте. Это может быть использовано для очень быстрого получения UIImage.

Я реализовал метод категории на UIView, чтобы получить представление как 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;
}

Это значительно быстрее, чем существующий метод renderInContext:.

Ссылка: https://developer.apple.com/library/content/qa/qa1817/_index.html

ОБНОВЛЕНИЕ ДЛЯ SWIFT : расширение, которое делает то же самое:

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
    }
}

ОБНОВЛЕНИЕ ДЛЯ SWIFT 3

    UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)

    drawHierarchy(in: self.bounds, afterScreenUpdates: true)

    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
73 голосов
/ 07 февраля 2010

Я думаю, что вы можете renderInContext, а не drawInContext. drawInContext - это больше метод, который вы бы переопределили ...

Обратите внимание, что он может работать не во всех видах, в частности, год или около того назад, когда я пытался использовать его с просмотром с камеры в реальном времени, он не работал.

61 голосов
/ 15 мая 2012

Вам нужно захватить окно ключа для скриншота или UIView. Вы можете сделать это в Retina Resolution , используя UIGraphicsBeginImageContextWithOptions и установить его масштабный параметр 0.0f. Он всегда записывает в собственном разрешении (сетчатка для iPhone 4 и более поздних версий).

Этот снимок экрана в полноэкранном режиме (окно ключа)

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();

Этот код захватывает UIView в собственном разрешении

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

Сохраняет UIImage в формате jpg с 95% качеством в папке документов приложения, если вам нужно это сделать.

NSString  *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/capturedImage.jpg"]];    
[UIImageJPEGRepresentation(capturedImage, 0.95) writeToFile:imagePath atomically:YES];
21 голосов
/ 20 января 2014

iOS7 и далее, у нас есть методы по умолчанию ниже:

- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates

Вызов метода выше выполняется быстрее, чем попытка отобразить содержимое текущего представления в растровое изображение самостоятельно.

Если вы хотите применить графический снимок, например размытие, к снимку, используйте метод drawViewHierarchyInRect:afterScreenUpdates:.

https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html

10 голосов
/ 01 мая 2018

Появился новый API от iOS 10

extension UIView {
    func makeScreenshot() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: self.bounds)
        return renderer.image { (context) in
            self.layer.render(in: context.cgContext)
        }
    }
}
10 голосов
/ 14 июня 2015

Я создал полезное расширение для UIView, чтобы снимать скриншот в Swift:

extension UIView{

var screenshot: UIImage{

    UIGraphicsBeginImageContext(self.bounds.size);
    let context = UIGraphicsGetCurrentContext();
    self.layer.renderInContext(context)
    let screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return screenShot
}
}

Чтобы использовать это просто введите:

let screenshot = view.screenshot
7 голосов
/ 07 февраля 2010
- (void)drawRect:(CGRect)rect {
  UIGraphicsBeginImageContext(self.bounds.size);    
  [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);  
}

Этот метод может поместить в ваш класс контроллера.

5 голосов
/ 07 февраля 2010
CGImageRef UIGetScreenImage();

Apple теперь позволяет нам использовать его в общедоступном приложении, даже если это частный API

4 голосов
/ 21 сентября 2015

Я создал это расширение для сохранения снимка экрана из 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)

}}

вызов

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

Если вы хотите создать PNG, необходимо изменить:

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

от

UIImagePNGRepresentation(image)?.writeToFile(path, atomically: true)
4 голосов
/ 04 октября 2010

Apple не позволяет:

CGImageRef UIGetScreenImage();

Приложения должны делать снимок экрана, используя метод drawRect, указанный в: http://developer.apple.com/library/ios/#qa/qa2010/qa1703.html

...