On iOS10 snapshotView takes snapshot before the view is completely rendered
Asked Answered
D

2

7

I have fully transparent a table and navigation controllers. Because of this, when pushing new view controllers the animation was broken. Therefore I added my own custom push transition which takes snapshot of the next view controller and animates that.

This no longer works on iOS10. snapshotView(afterScreenUpdates: true) returns a view that is pure white. I also tried getting the snapshot with the old method through graphics context and it didn't work too.

How can I be sure that the view being pushed to the navigation controller is loaded before snapshotView? Or is there a better way to solve this? This is a breaking change for me unfortunately..

Dianthus answered 18/9, 2016 at 10:31 Comment(3)
I'm wondering how that ever could worked. You take a snapshot of a view, before it got visible. Can you explain a bit more in detail? Where exactly do you do the snapshot? How do you do the transition and of course: does your first problem with the messed up transition still exist?Clemens
I am seeing the same thing on iPhone 7 (or 7 Plus) Simulators only. Other simulators and devices seem unaffected.Vouchsafe
Same thing happens on both Device (iPhone 6S) and Simulator on iOS 13. I had to use proposed snapshotImageView() method instead.Abrahamabrahams
I
8

I want to just say that this is strictly an iPhone 7 simulator and iPhone 7+ simulator issue. The issue will not appear on a real device. If you need to fix this for the simulator here is a work around I found in Pod: https://github.com/NewAmsterdamLabs/ZOZolaZoomTransition/

- (UIImage *)zo_snapshot {
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, [UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.layer renderInContext:context];
    UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshot;
}
Insphere answered 10/11, 2016 at 19:47 Comment(1)
I beileve you mean iPhone 7 and iPhone 7+ simulator. The same issue occurred for me where the snapshot view was not working as expected for those simulators. Switching to a different simulator fixed the issue. Wierd.Epicrisis
B
2

This extension should fix the issue

extension UIView {
    /// Replacement of `snapshotView` on iOS 10. Fixes the issue of `snapshotView` returning a blank white screen.
    func snapshotImageView() -> UIImageView? {
        UIGraphicsBeginImageContext(bounds.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }

        layer.render(in: context)

        let viewImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return UIImageView(image: viewImage, highlightedImage: viewImage)
    }
}
Beitz answered 21/9, 2016 at 21:20 Comment(4)
This seems it may work but it's visual quality is very bad. I tried to do this but it didn't work : let scale = self.contentScaleFactor; context.scaleBy(x: scale, y: scale);Dianthus
@Dianthus Can you try replacing UIGraphicsBeginImageContext(bounds.size) with UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0). Let me know if it improves the quality.Beitz
Unfortunately I found out that this code block does not solve it. At first, I thought that it solved it but it seems like I was keeping my delayed processing hacks.. When I cleaned my hacks, it still shows black.. My hack is: I add the upcoming view to the screen. I take snapshot of it and remove it after DispatchQueue.main.asyncAfter 0.1ms later. So it allows time to it to draw render itself :/Dianthus
Answering a question by just telling the OP to use a completely different API without explaining why isn't ideal. It would be nice to understand exactly whats different and why you recommended this approachLabiodental

© 2022 - 2024 — McMap. All rights reserved.