В iOS10 snapshotView делает снимок до того, как представление будет полностью отрисовано.

У меня полностью прозрачная таблица и контроллеры навигации. Из-за этого при нажатии новых контроллеров представления анимация прерывалась. Поэтому я добавил свой собственный push-переход, который делает снимок следующего контроллера представления и анимирует его.

Это больше не работает на iOS10. snapshotView(afterScreenUpdates: true) возвращает представление чисто белого цвета. Я также пытался получить снимок старым методом через графический контекст, и это тоже не сработало.

Как я могу быть уверен, что представление, передаваемое в контроллер навигации, загружается до моментального снимка? Или есть лучший способ решить эту проблему? Это критическое изменение для меня, к сожалению ..


person frankish    schedule 18.09.2016    source источник
comment
Мне интересно, как это когда-либо могло работать. Вы делаете снимок вида до того, как он станет видимым. Можете ли вы объяснить немного подробнее? Где именно вы делаете снимок? Как вы делаете переход и, конечно же, ваша первая проблема с испорченным переходом все еще существует?   -  person jboi    schedule 18.09.2016
comment
Я вижу то же самое только на симуляторах iPhone 7 (или 7 Plus). Другие симуляторы и устройства кажутся нетронутыми.   -  person Keller    schedule 22.09.2016
comment
То же самое происходит как на устройстве (iPhone 6S), так и на симуляторе на iOS 13. Вместо этого мне пришлось использовать предложенный метод snapshotImageView().   -  person Borzh    schedule 03.12.2020


Ответы (2)


Я хочу просто сказать, что это строго проблема симулятора iPhone 7 и симулятора iPhone 7+. Проблема не появится на реальном устройстве. Если вам нужно исправить это для симулятора, вот обходной путь, который я нашел в 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;
}
person HannahCarney    schedule 10.11.2016
comment
Я полагаю, вы имеете в виду симулятор iPhone 7 и iPhone 7+. У меня возникла та же проблема, когда представление моментального снимка не работало должным образом для этих симуляторов. Переключение на другой симулятор решило проблему. Странный. - person Idr; 03.01.2017

Это расширение должно решить проблему

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)
    }
}
person Bebekucing    schedule 21.09.2016
comment
Кажется, это может работать, но визуальное качество очень плохое. Я пытался сделать это, но это не сработало: let scale = self.contentScaleFactor; context.scaleBy(x: scale, y: scale); - person frankish; 22.09.2016
comment
@frankish Можете ли вы попробовать заменить UIGraphicsBeginImageContext(bounds.size) на UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0). Дайте мне знать, если это улучшит качество. - person Bebekucing; 22.09.2016
comment
К сожалению, я обнаружил, что этот блок кода не решает эту проблему. Сначала я думал, что это решило эту проблему, но, похоже, я сохранил свои отложенные хаки обработки. Когда я очистил свои хаки, он по-прежнему отображается черным. Мой хак: я добавляю предстоящее представление на экран. Я делаю снимок и удаляю его через DispatchQueue.main.asyncAfter 0.1ms позже. Так что это дает ему время, чтобы отрисовать сам рендер :/ - person frankish; 22.09.2016
comment
Отвечая на вопрос, просто сказав OP использовать совершенно другой API, не объясняя, почему, это не идеально. Было бы неплохо понять, что именно отличается и почему вы рекомендовали этот подход - person Daniel Galasko; 25.10.2016