ios objective-c ios10 xcode8 uivisualeffectview

UIVisualEffectView en iOS 10



objective-c ios10 (3)

El código a continuación desdibuja el controlador de vista principal cuando se presenta ViewController. Probado tanto en iOS9 como en 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

Estoy presentando un UIViewController que contiene un UIVisualEffectView de la siguiente manera:

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

Como puede ver, estoy usando UIModalPresentationStyleOverFullScreen para que cuando aparezca el controlador de vista con desenfoque, el desenfoque se ''aplique'' al contenido del controlador de vista que lo presenta; el segue tiene un estilo de transición de Disolución cruzada.

El efecto se ve como se esperaba. Sin embargo, en iOS 9 la presentación es más suave que en iOS 10. En iOS 10 cuando aparece el controlador de vista parece una animación de 2 pasos, mientras que en iOS 9 el desenfoque se aplica de inmediato.

Una imagen vale más que mil palabras, así que subí un video que muestra este extraño comportamiento:

UIVisualEffectView iOS 9 vs iOS 10

Mi pregunta es: ¿cómo puedo presentar el controlador de vista en iOS 10 ya que se presenta en iOS 9?


iOS 10 ha cambiado la forma en que UIVisualEffectView funciona, y ha roto muchos casos de uso que no eran estrictamente "legales", pero que funcionaban antes. Al apegarse a la documentación, no debería estar desapareciendo en UIVisualEffectView , que es lo que sucede cuando utiliza UIModalTransitionStyleCrossDissolve . Ahora parece estar roto en iOS 10, junto con el enmascaramiento de vistas de efectos visuales, y otros.

En su caso, sugeriría una solución fácil que también creará un efecto mejor que antes, y se admite tanto en iOS 9 como en 10. Cree una presentación personalizada y, en lugar de atenuar la vista, anime la propiedad del effect de nil a efecto de desenfoque. Puede desaparecer en el resto de la jerarquía de vistas si es necesario. Esto animará nítidamente el radio de desenfoque similar a como se ve cuando tira de los iconos de la pantalla de inicio hacia abajo.


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

Probado en iOS9 y 10. Funciona bien para mí