UIScrollView no obtiene un nuevo tamaño en el cambio de orientación

Tengo un ejemplo UIScrollView muy simple que simplemente no hace lo que se supone que debe hacer. No estoy seguro si se trata de un error con la API o un error en mi código.

Básicamente, tengo un UIViewController con un UIScrollView como su vista. Cuando lo agrego a la UIWindow y cambio la orientación del iPad, desconecto el tamaño de UIScrollView , que es incorrecto (?) Informado.

Aquí está mi implementación UIViewController :

 @implementation CustomViewController - (void)loadView { scrollView = [[[UIScrollView alloc] init] autorelease]; scrollView.delegate = self; scrollView.backgroundColor = [UIColor networkingColor]; self.view = scrollView; } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { CGSize rect = scrollView.frame.size; NSLog(@"will rotate w%fh%f", rect.width, rect.height); } - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { CGSize rect = scrollView.frame.size; NSLog(@"will animate rotation w%fh%f", rect.width, rect.height); } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { CGSize rect = scrollView.frame.size; NSLog(@"did rotate w%fh%f", rect.width, rect.height); } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } @end 

Cuando ejecuto el código anterior, veo las siguientes inputs en mi console:

 2010-07-11 11:03:05.214 Untitled2[6682:207] will rotate w768.000000 h1004.000000 2010-07-11 11:03:05.214 Untitled2[6682:207] will animate rotation w748.000000 h1024.000000 2010-07-11 11:03:05.619 Untitled2[6682:207] did rotate w748.000000 h1024.000000 2010-07-11 11:03:07.951 Untitled2[6682:207] will rotate w748.000000 h1024.000000 2010-07-11 11:03:07.958 Untitled2[6682:207] will animate rotation w768.000000 h1004.000000 2010-07-11 11:03:08.367 Untitled2[6682:207] did rotate w768.000000 h1004.000000 

Como puede ver, los cambios de orientación cambian el tamaño de UIScrollView , pero solo para permitir la nueva barra de estado. Espero que el ancho y la altura cambien drásticamente, ya que UIScrollView es lo más ancho que es alto y viceversa.

¿Hay alguna manera de que UIScrollView informe que es tamaño real?

Tengo la respuesta si todavía estás mirando. Prueba los límites , no el marco.

Motivo: frame es una propiedad derivada de los límites y la transformación que se aplica para la rotation.

Las vistas no cambiarán de tamaño automáticamente cuando cambien el tamaño de sus supervisas a less que las configure específicamente. Para esa vista de desplazamiento, necesitaría decirle que cambie el tamaño de su ancho y alto cuando lo haga su vista de supervisión.

 scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 

He notado que determinar el nuevo contentSize didRotateFromInterfaceOrientation en didRotateFromInterfaceOrientation también es imposible si empiezas con un file NIB de iPhone en lugar de un file NIB de iPad dedicado: los fotogtwigs en el file NIB de iPhone son mucho más pequeños y, por lo tanto, la altura calculada del contenido se vuelve mucho mayor mayor de lo que debería ser cuando estás realmente en un iPad. Apple DID dice que DEBO crear un file iPad NIB por separado …

Entonces, también obtengo las dimensiones antiguas en didRotateFromInterfaceOrientation , pero para mí ahora es un problema menor, ya que iOS maneja todo bien una vez que empiezo con el file NIB correcto. Aun así, parece less intuitivo para mí que en el método didRotateFromInterfaceOrientation , las dimensiones del marco son incorrectas para la vista actual.

PD. Encontré una solución al final, solo use las notifications en lugar de didRotateFromInterfaceOrientation .

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

Luego, en el método orientationChanged , ajuste las vistas a los nuevos frameworks. Tuve un problema final: si la orientación inicial era diferente de la orientación en la punta, la vista seguiría siendo incorrecta, resolví eso creando un nuevo file NIB especialmente para la vista de paisaje. En el método init, ViewController elige qué NIB carga según la orientación actual.

No sé que es de ayuda porque nunca probé esto, pero creo que podría ayudarlo

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { self.view = scrollView; CGSize rect = scrollView.frame.size; NSLog(@"will rotate w%fh%f", rect.width, rect.height); } - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { self.view = scrollView; CGSize rect = scrollView.frame.size; NSLog(@"will animate rotation w%fh%f", rect.width, rect.height); } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { self.view = scrollView; CGSize rect = scrollView.frame.size; NSLog(@"did rotate w%fh%f", rect.width, rect.height); } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } 

Normalmente soluciono eso estableciendo un valor de contentSize en 0 como CGSizeMake(contentSize.width, 0) para la vista horizontal.

Para forzar que UIScrollView desplace solo, por ejemplo, el valor no desplazable del set horizontal para contentSize a 0> CGSizeMake(contentSize.width, 0) .

Espero que ayude.