Jak przekonwertować UIView na obraz

98

Chcę przekonwertować UIView na obraz i zapisać go w mojej aplikacji. Czy ktoś może mi powiedzieć, jak zrobić zrzut ekranu widoku lub przekonwertować go na obraz i jaki jest najlepszy sposób, aby zapisać go w aplikacji (nie w rolce z aparatu)? Oto kod widoku:

var overView   = UIView(frame: CGRectMake(0, 0, self.view.frame.width/1.3, self.view.frame.height/1.3))
overView.center = CGPointMake(CGRectGetMidX(self.view.bounds),
CGRectGetMidY(self.view.bounds)-self.view.frame.height/16);
overView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(overView)
self.view.bringSubviewToFront(overView)
Sameer Hussain
źródło
Istotne również: stackoverflow.com/q/59592933/294884
Fattie

Odpowiedzi:

196

Rozszerzenie na UIViewpowinno załatwić sprawę.

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

Apple odradza UIGraphicsBeginImageContexturuchamianie iOS 10 wraz z wprowadzeniem gamy kolorów P3. UIGraphicsBeginImageContextjest sRGB i tylko w wersji 32-bitowej. Wprowadzili nowy UIGraphicsImageRendererinterfejs API, który jest w pełni zarządzany kolorami, oparty na blokach, ma podklasy dla plików PDF i obrazów oraz automatycznie zarządza okresem życia kontekstu. Sprawdź sesję WWDC16 205, aby uzyskać więcej informacji (renderowanie obrazu zaczyna się około godziny 11:50)

Aby mieć pewność, że działa na każdym urządzeniu, użyj #availablez powrotem do wcześniejszych wersji iOS:

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContext(self.frame.size)
            self.layer.render(in:UIGraphicsGetCurrentContext()!)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return UIImage(cgImage: image!.cgImage!)
        }
    }
}
Naveed J.
źródło
9
Powinno to być oznaczone jako poprawna odpowiedź. Wszystkie inne opcje spowodują, że renderowany obraz straci przejrzystość i będzie wyglądał na pikselowy / rozmazany.
TuplingD
Jedyny słuszny sposób! Dla początkujących użycie to: let image = customView.asImage ()
Fabio
1
Czy można renderować UIView z przezroczystym tłem? Mój ma zaokrąglone rogi.
IXany
@ixany To powinno już się tym zająć. Właśnie wypróbowałem to na placu zabaw i zadziałało: let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)); view.backgroundColor = .black; view.layer.cornerRadius = 9; view.asImage();
Naveed J.
2
Dziękuję Ci! Jeśli ktoś wie, byłbym ciekawy, jakie są różnice w kodzie z hackingwithswift.com/example-code/media/… : return renderer.image {ctx in drawHierarchy (in: bounds, afterScreenUpdates: true)}
Kqtr
64

możesz użyć rozszerzenia

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}

Tutaj szybka wersja 3/4:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}
Bao Tuan Diep
źródło
5
Wstydzę się, że o to pytam, ale jak mam to nazwać? Nie mam obrazu i UIView, którym chcę być obrazem. Powyższy kod daje mi rozszerzenie UIImage ... ale co teraz?
Dave G,
8
let image = UIImage(view: myView)
doctorBroctor,
Nie działa dla mnie, ponieważ UIGraphicsGetCurrentContext () może mieć wartość nil i kod ulega awarii.
Juan Carlos Ospina Gonzalez
@JuanCarlosOspinaGonzalez Jeśli UIGraphicsGetCurrentContext zwrócił zero, podejrzewam, że musisz sprawdzić UIGraphicsBeginImageContext, aby dowiedzieć się, dlaczego się nie udało. Domyślam się, że jeden z wymiarów twojego rozmiaru jest zerowy lub w inny sposób nieważny, ale tak naprawdę nie mam pojęcia, co może spowodować, że to się nie powiedzie.
John Stephen,
2
należy również pamiętać o skali ekranu, więc zastąpiłbym pierwszą linię inicjalizatora tym: UIGraphicsBeginImageContextWithOptions(view.frame.size, false, UIScreen.main.scale)
iVentis
41

Konwertuj swój UIView na obraz przez drawViewHierarchyInRect: afterScreenUpdates: który jest wielokrotnie szybszy niż renderInContext

Ważna uwaga: nie wywołuj tej funkcji z viewDidLoad lub viewWillAppear , upewnij się, że przechwytujesz widok po jego wyświetleniu / załadowaniu w pełni

Obj C

     UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.opaque, 0.0f);
     [myView drawViewHierarchyInRect:myView.bounds afterScreenUpdates:NO];
     UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     myImageView.image =  snapshotImageFromMyView;

Zapisz edytowany obraz Album fotograficzny

     UIImageWriteToSavedPhotosAlbum(snapshotImageFromMyView, nil,nil, nil);

Swift 3/4

    UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.isOpaque, 0.0)
    myView.drawHierarchy(in: myView.bounds, afterScreenUpdates: false)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    print(snapshotImageFromMyView)
    myImageView.image = snapshotImageFromMyView

Super łatwa generalizacja z rozszerzeniem, iOS11, swift3 / 4

extension UIImage{
    convenience init(view: UIView) {

    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    self.init(cgImage: (image?.cgImage)!)

  }
}


Use : 
 //myView is completly loaded/visible , calling this code after only after viewDidAppear is call
 imgVV.image = UIImage.init(view: myView)
 // Simple image object
 let img =  UIImage.init(view: myView)
ViJay Avhad
źródło
3
Nie działa dla mnie Mam czarny ekran dla mojego UiImage
Badr Filali
Naprawdę ?? Czy możesz wkleić tutaj swój kod? Być może używasz niewłaściwego obiektu UIView do konwersji jako UIImage.
ViJay Avhad
`func convertViewIntoImg () -> Void {imgFakeCard.image = UIImage.init (view: card)}` Z twoim rozszerzeniem w swift 3 ta funkcja jest wywoływana w viewDidLoad
Badr Filali
1
Dziękujemy za przesłanie kodu i wspomnienie, że zadzwoniłeś do viewDidLoad. Oto, co poszło nie tak. Przechwytujesz migawkę widoku przed załadowaniem go do pamięci. Spróbuj zadzwonić pod kod w viewDidAppear, co na pewno rozwiąże problem. Wszelkie pytania prosimy o odpowiedź.
ViJay Avhad
To działa świetnie, dzięki, problem pojawił się skąd zadzwoniłem do twojego rozszerzenia
Badr Filali
20

W systemie iOS 10:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)
    }
}
afrodev
źródło
1
prowadzi to do awarii.
KingPolygon
18

Najlepsza praktyka od iOS 10 i Swift 3

podczas gdy nadal obsługuje iOS 9 i wcześniejsze wersje nadal działa od iOS 13, Xcode 11.1, Swift 5.1

extension UIView {

    func asImage() -> UIImage? {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
            defer { UIGraphicsEndImageContext() }
            guard let currentContext = UIGraphicsGetCurrentContext() else {
                return nil
            }
            self.layer.render(in: currentContext)
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
}

Nie jestem pewien, co oznacza to pytanie:

jaki jest najlepszy sposób na zapisanie go w aplikacji (nie w rolce z aparatu)?

Jon Willis
źródło
17
    UIGraphicsBeginImageContext(self.view.bounds.size);        
    self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
    var screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
Vakas
źródło
1
UIGraphicsGetImageFromCurrentImageContext zwraca UIImage. Nie ma potrzeby, aby rzucić to na UIImage
Leo Dabus.
To robi zrzut ekranu całego widoku, tak? Chcę po prostu przekonwertować UIView, tj. Przegląd w moim kodzie, który jest podziałem self.view na obraz. Nie cały widok!
Sameer Hussain
@Vakas, gdy próbowałem wydrukować obraz image.it jest zbyt mały. Jakie jest rozwiązanie tego
problemu
6
Obraz zrzutu ekranu nie ma dobrej jakości, co mam zrobić?
Neela
13

Na przykład, jeśli mam widok rozmiaru: 50 50 na 100,100. Mogę zrobić zrzut ekranu:

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), false, 0);
    self.view.drawViewHierarchyInRect(CGRectMake(-50,-5-,view.bounds.size.width,view.bounds.size.height), afterScreenUpdates: true)
    var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
Sameer Hussain
źródło
w linii self.view jest błąd w parametrze. myślę, że powinno być -5, a nie -5-
Krutarth Patel
@sameer mam jedno pytanie. kiedy drukuję to zdjęcie jest za małe
Krutarth Patel
7

Moim zdaniem podejście z inicjatorem nie jest takie świetne, ponieważ tworzy dwa obrazy.

Wolę to:

extension UIView {
    var snapshot: UIImage? {
        UIGraphicsBeginImageContext(self.frame.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Tino
źródło
Właściwość należy nazwać czymś innym niż image. Może to kolidować z podklasami, które mają właściwości o nazwie image, takie jak UIImageView.
Hobbes the Tige,
Zastosowałem się do sugestii @HobbestheTige i zmieniono nazwę nieruchomości
Tino
6

Swift 4.2, iOS 10

extension UIView {

    // If Swift version is lower than 4.2, 
    // You should change the name. (ex. var renderedImage: UIImage?)

    var image: UIImage? {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) }
    }
}

Próba

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .blue

let view2 = UIView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
view2.backgroundColor = .red
view.addSubview(view2)

let imageView = UIImageView(image: view.image)

wprowadź opis obrazu tutaj

Legowisko
źródło
Chciałem tylko zwrócić uwagę, że jeśli używasz w swoim projekcie jakichkolwiek UIImageViews, to musi mieć inną nazwę, w przeciwnym razie .image stanie się tylko do odczytu. Może nazwij to „screenCapture” zamiast „image”.
Chris,
@Chris Yeah, masz rację. Należy zmienić nazwę, jeśli wersja Swift jest niższa niż 4.2. Dziękuję za wskazanie błędu.
Den
6

Działa to dla mnie dla Xcode 9 / Swift 3.2 / Swift 4 i Xcode 8 / Swift 3

 if #available(iOS 10.0, *) {

     // for Xcode 9/Swift 3.2/Swift 4 -Paul Hudson's code
     let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
     let capturedImage = renderer.image { 
         (ctx) in
         view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
     }
     return capturedImage

 } else {

     // for Xcode 8/Swift 3
     UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
     view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
     let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()
     return capturedImage!
 }

Oto jak go używać wewnątrz funkcji:

fileprivate func captureUIImageFromUIView(_ view:UIView?) -> UIImage {

     guard (view != nil) else{

        // if the view is nil (it's happened to me) return an alternative image
        let errorImage = UIImage(named: "Error Image")
        return errorImage
     }

     // if the view is all good then convert the image inside the view to a uiimage
     if #available(iOS 10.0, *) {

         let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
         let capturedImage = renderer.image { 
             (ctx) in
             view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
         }
         return capturedImage

     } else {

         UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
         view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
         let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
         UIGraphicsEndImageContext()
         return capturedImage!
     }
}

Oto jak zrobić coś z obrazem zwróconym przez funkcję:

@IBOutlet weak fileprivate var myCustomView: UIView!
var myPic: UIImage?

let myImageView = UIImageView()

@IBAction fileprivate func saveImageButtonTapped(_ sender: UIButton) {

   myPic = captureUIImageFromUIView(myCustomView)

   // display the pic inside a UIImageView
   myImageView.image = myPic!
}

Otrzymałem odpowiedź Xcode 9 / Swift 3.2 / Swift 4 od Paula Hudsona przekonwertować uiview na uiimage

Mam Xcode 8 / Swift 3 skądś na SO dawno temu i zapomniałem gdzie :(

Lance Samaria
źródło
Gdzie jest wyświetlany i / lub zapisywany obraz?
Famic Tech
@FamicTech Po utworzeniu obrazu młodzież decyduje, co z nim zrobić. W przykładzie z mojego kodu właśnie przekonwertowałem UIView na UIImage o nazwie „myPic”, ale nic nie zrobiłem z „myPic”. Następnym możliwym krokiem jest wyświetlenie „myPic” wewnątrz UIImageVIew w następujący sposób: myImageVIew.image = myPic. Jeśli używasz collectionView i chciałbyś wyświetlić w nim obrazy, tworzysz UIImageVIew w każdej komórce, a następnie wyświetlasz obraz (myPic) wewnątrz UIImageVIew za pośrednictwem indexPath.item ze źródła danych ex: myImageView.image = dataSource [indexPath .item] .myPic
Lance Samaria,
@FamicTech Popełniasz niewielki błąd. Nie ma to nic wspólnego z collectionVIew. Masz 2 różne typy klas: UIImage i UIView. Oba mogą służyć do wyświetlania dowolnego obrazu, ale oba robią to na różne sposoby. Prawie wszystko w iOS jest podklasą UIView, ale UIImage może wyświetlać tylko obrazy (2 różne rzeczy). To, co robi ta funkcja, to pobranie UIVIew i przekonwertowanie go na UIImage. Łatwiejszy np. Jeśli chcesz przekonwertować 4.0 (Double) na 4 (Int), rzuć to Int (4.0), wynik to 4. Ale z tym konwertujesz obraz wewnątrz UIVIew na UIImage. Rozumiesz?
Lance Samaria
to, co próbuję zrobić, to pozwolić użytkownikowi przejść do mojego kontrolera widoku kolekcji i nacisnąć przycisk, który powinien przyjąć bieżący widok, który jest widokiem kolekcji 10x10 i utworzyć obraz całej siatki 10x10 (należy pamiętać, że cały siatka nie jest w pełni widoczna w widoku). Czy powyższy kod rozwiązuje ten przypadek użycia?
Famic Tech
Przycisk znajduje się w kontrolerze nawigacji. Użytkownik kliknąłby go i „powinien” przejść do widoku zbioru wyświetlanego pod kontrolerem nawigacji i utworzyć obraz widoku zbioru (działałby również plik PDF) ze wszystkimi informacjami w komórkach w widoku zbioru.
Famic Tech
5
var snapshot = overView.snapshotViewAfterScreenUpdates(false)

lub w celu-c

UIView* snapshot = [overView snapshotViewAfterScreenUpdates:NO];
Yedidya Reiss
źródło
Czy imageView to to samo co image? Jeśli tak, jak mogę go zapisać w mojej aplikacji?
Sameer Hussain
4

Możesz go łatwo używać, używając takiego rozszerzenia

// Take a snapshot from a view (just one view)
let viewSnapshot = myView.snapshot

// Take a screenshot (with every views in screen)
let screenSnapshot = UIApplication.shared.snapshot

// Take a snapshot from UIImage initialization
UIImage(view: self.view)

Jeśli chcesz użyć tych metod / zmiennych rozszerzających, zaimplementuj to

  1. Rozszerzenie UIImage

    extension UIImage {
        convenience init(view: UIView) {
            if let cgImage = view.snapshot?.cgImage {
                self.init(cgImage: cgImage)
            } else {
                self.init()
            }
        }
    }
    
  2. Rozszerzenie UIView

    extension UIView {
    
        var snapshot: UIImage? {
            UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0.0)
            if UIGraphicsGetCurrentContext() != nil {
                drawHierarchy(in: bounds, afterScreenUpdates: true)
                let screenshot = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return screenshot
            }
            return nil
        }
    }
    
  3. Rozszerzenie UIApplication

    extension UIApplication {
    
        var snapshot: UIImage? {
            return keyWindow?.rootViewController?.view.snapshot
        }
    }
    
Khemmachart Chutapetch
źródło
Miałem widok z podwidokami zmanipulowanymi pozycjami, a inne odpowiedzi nie dały mi prawidłowych pozycji w warstwach, dziękuję.
Ashkan Ghodrat
3

lub iOS 10+ możesz użyć nowego UIGraphicsImageRenderer + zalecanej drawHierarchy, która w niektórych sytuacjach może być znacznie szybsza niż layer.renderInContext

extension UIView {
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
        return renderer.image { _ in
            self.drawHierarchy(in: CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height), afterScreenUpdates: false)
        }
    }
}
Морт
źródło
3

Dzięki @ Bao Tuan Diep! Chcę dodać suplement.

Kiedy używasz kodu:

yourView.layer.render(in:UIGraphicsGetCurrentContext()!)

Musisz zauważyć, że:

 - If you had used `autoLayout` or `Masonry` in `yourView` (that you want to convert) .
 - If you did not add `yourView` to another view which means that `yourView` was not used as a subview but just an object.

Następnie musisz użyć :

[yourView setNeedsLayout];
[yourView layoutIfNeeded];

zaktualizować yourViewwcześniej yourView.layer.render(in:UIGraphicsGetCurrentContext()!).

W przeciwnym razie możesz otrzymać obiekt obrazu, który nie zawiera żadnych elementów

guozqzzu
źródło
Dzięki za to. Bardzo pomogło !!
Maksim Kniazev
2

Swift 4.2

import Foundation
import UIKit  

extension UIImage {

    convenience init(view: UIView) {

        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
        view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)

    } 
}

za pomocą:

let img = UIImage.init (widok: self.holderView)

reza_khalafi
źródło
1

Wdrożenie w Swift 3 :

Dodaj poniższy kod poza zakresem klasy.

extension UIImage {
    convenience init(_ view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)
    }
}

Stosowanie :

let image = UIImage( Your_View_Outlet )
Roy
źródło
otrzymywanie błędu „Rysowanie widoku (0x1040a6970, UIView), który nie został wyrenderowany co najmniej raz, wymaga”
kishu mewara
0

I wdrożone @Naveed J. ten sposób i zadziałała jak urok.

Oto jego zakres:

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

Oto jak to wdrożyłem.

//create an image from yourView to display
//determine the frame of the view/imageimage
let screen = self.superview!.bounds
let width = screen.width / 4 //make image 1/4 width of screen
let height = width
let frame = CGRect(x: 0, y: 0, width: width, height: height)
let x = (screen.size.width - frame.size.width) * 0.5
let y = (screen.size.height - frame.size.height) * 0.5
let mainFrame = CGRect(x: x, y: y, width: frame.size.width, height: frame.size.height)

let yourView = YourView() //instantiate yourView
yourView.frame = mainFrame //give it the frame
yourView.setNeedsDisplay() //tell it to display (I am not 100% sure this is needed)

let characterViewImage = yourView.asImage()
Jacob F. Davis C-CISO
źródło
0

Inicjator z nowym UIGraphicsImageRenderer dostępnym od iOS 10:

extension UIImage{
    convenience init(view: UIView) {

    let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
    let canvas = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height)
    let image = renderer.image { _ in
        self.drawHierarchy(in: canvas, afterScreenUpdates: false)
    }
    self.init(cgImage: (image?.cgImage)!)
  }
}
Frédéric Adda
źródło
0

współpracuj ze mną dobrze!

Swift4

 extension UIView {

    func toImage() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
        self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
        let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return snapshotImageFromMyView!
    }

    }
Faris
źródło
return snapshotImageFromMyView!Wątek 1: Błąd krytyczny: nieoczekiwanie znaleziono zero podczas rozpakowywania wartości opcjonalnej
Takasur,
0

W przypadku widoku zawiera rozmyty widok podrzędny (np. Instancja UIVisualEffectView ), tylko drawViewHierarchyInRect: afterScreenUpdates .

Odpowiedź @ViJay Avhad jest prawidłowa w tym przypadku.

rafalkitta
źródło
0

Korzystanie z UIGraphicsImageRenderer nie działa, gdy widok zawiera podglądy zestawu scen, metalowe lub z zestawu Sprite. W takich przypadkach użyj

let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image { ctx in
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}
johnnyMac
źródło
-1
please try below code.
-(UIImage *)getMainImageFromContext
{
UIGraphicsBeginImageContextWithOptions(viewBG.bounds.size, viewBG.opaque, 0.0);
[viewBG.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
herry.master
źródło