Подтвердить что ты не робот

UIVisualEffectView в iOS 10

Я представляю UIViewController, который содержит UIVisualEffectView следующим образом:

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    [self performSegueWithIdentifier:@"segueBlur" sender:nil];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"segueBlur"]) {
        ((UIViewController *)segue.destinationViewController).providesPresentationContextTransitionStyle = YES;
        ((UIViewController *)segue.destinationViewController).definesPresentationContext = YES;
        ((UIViewController *)segue.destinationViewController).modalPresentationStyle = UIModalPresentationOverFullScreen;
    }
}

Как вы можете видеть, я использую UIModalPresentationStyleOverFullScreen, так что, когда появляется контроллер вида с размытием, размытие будет "применено" к содержимому контроллера представления, который его представляет; segue имеет стиль перехода Cross Dissolve.

Эффект выглядит так, как ожидалось. Однако в iOS 9 презентация более плавная, чем в iOS 10. В iOS 10, когда появляется контроллер представления, кажется, что это двухэтапная анимация, в то время как в iOS 9 размытие применяется немедленно.

Изображение стоит тысячи слов, поэтому я загрузил видео, показывающее это странное поведение:

UIVisualEffectView iOS 9 vs iOS 10

Мой вопрос: как я могу представить контроллер представления в iOS 10, поскольку он представлен в iOS 9?

4b9b3361

Ответ 1

iOS 10 изменил способ работы UIVisualEffectView, и он нарушил множество вариантов использования, которые не были строго "законными", но работали раньше. Придерживаясь документации, вы не должны исчезать в UIVisualEffectView, что происходит, когда вы используете UIModalTransitionStyleCrossDissolve. Кажется, теперь он сломан на iOS 10, а также маскирует визуальные эффекты и другие.

В вашем случае я бы предложил простое исправление, которое также создаст лучший эффект, чем раньше, и будет поддерживаться как для iOS 9, так и для 10. Создайте собственную презентацию и вместо того, чтобы затухать вид, анимируйте effect свойство от nil к эффекту размытия. При необходимости вы можете погрязнуть в остальной иерархии вашего представления. Это аккуратно оживит радиус размытия, похожий на то, как он выглядит, когда вы вытаскиваете значки на главном экране.

Ответ 2

    UIView.animate(withDuration: 0.5) {
        self.effectView.effect = UIBlurEffect(style: .light)
    }

Протестировано как на iOS9, так и на 10. Работает отлично для меня

Ответ 3

Код ниже размытия контроллера родительского представления при представлении ViewController. Протестировано как на iOS9, так и на 10.

@interface ViewController () <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>

@property (nonatomic) UIVisualEffectView *blurView;

@end


@implementation ViewController

- (instancetype)init
{
    self = [super init];
    if (!self)
        return nil;

    self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    self.transitioningDelegate = self;

    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor clearColor];
    self.blurView = [UIVisualEffectView new];
    [self.view addSubview:self.blurView];
    self.blurView.frame = self.view.bounds;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
                                                                       presentingController:(UIViewController *)presenting
                                                                   sourceController:(UIViewController *)source
{
    return self;
}

-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 0.3;
}

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIView *container = [transitionContext containerView];

    [container addSubview:self.view];

    self.blurView.effect = nil;

    [UIView animateWithDuration:0.3 animations:^{
        self.blurView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:finished];
    }];
}

@end