2009-07-09 13 views
28

Resumen: ¿Cómo debe saber el UIViewController el tamaño de su instancia de UIView al inicializar esa vista?Dónde determinar el tamaño de UIView

El método de inicialización dedicado para una UIView es el método initWithFrame:(CGRect)frame. Esto establece el marco para el UIView recién creado. Este método podría invocarse desde el método loadView UIViewController's, si se solicita la vista del controlador de vista. La documentación de UIViewController estados con respecto a la subclasificación y la vista de tamaño:

Al crear los puntos de vista de la jerarquía de vista , siempre se debe establecer las propiedades de tamaño automático de sus puntos de vista. Cuando se muestra un controlador de vista en pantalla, su vista raíz es típicamente redimensionada para ajustarse al espacio disponible, que puede variar dependiendo de la orientación actual de la ventana y la presencia de otros elementos de la interfaz tales como la barra de estado.

Por lo tanto, la instancia UIViewController debe establecer esas propiedades. Hasta ahora todo bien, el UIViewController hasta ahora no tiene que saber qué tan grande es o será su vista.

Cuando se solicita la vista de UIViewController y la propiedad de vista es nula, se invoca el método loadView del controlador de vista. Ahora hay un problema, porque el UIView necesita inicializarse, pero el controlador de vista aún no sabe qué tamaño debe tener la vista. ¿Qué tan grande debe inicializar esa vista? ¿Dónde en el código determina el tamaño de la vista?

Se podría iniciar la vista con un rect cero (CGRectZero):

- (void)loadView { 
    self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease]; 
} 

Y dejar que la persona que llama establece el marco de vista, así:

UIViewController *viewController = [[MyUIViewController alloc] init]; 
// next two lines are normally combined, but for clarity they are not now 
UIView *view = viewController.view; 
view.frame = CGRectMake(0, 0, 200, 200); 

Esto pide la vista desde el controlador de vista (viewController.view), y así carga su vista con el método loadView. Este método loadView inicializa la vista con un CGRectZero. Luego, la persona que llama establece su fotograma (view.frame = ...)

Lo que sucede es que la propiedad del fotograma en la vista se establece dos veces, posiblemente causando incluso más trabajo doble si su UIView personalizado está haciendo un diseño avanzado en el método setFrame (colocando y redimensionando subvistas por ejemplo). Puede evitar esto creando un método de inicialización dedicado para el UIViewController que ya le pide a la persona que llama para un CGRect, que almacenaría en un ivar. En el momento en que se llama al método loadView, usa este ivar para crear la vista.

¿Cuál es el mejor camino para ir aquí? ¿Configurando el marco de la vista dos veces (inicializando con CGRectZero, y estableciendo luego), o dando al UIViewController un nuevo método de inicialización con un CGRect (y dándole así una propiedad de marco)? ¿O me estoy perdiendo algo y hay otras posibilidades?

Respuesta

8

Usted no tiene que usar el inicializador designado. Simplemente use init como en [[UIView alloc] init]. El inicializador designado debe usarse desde los inicializadores de las subclases.

Por otro lado, establecer el marco dos veces no debería hacer mucho daño. La realización de muchas tareas en setFrame: es inusual. Layouting normalmente se realiza en layoutSubviews y solo se realiza una vez.

+10

método init UIView en realidad llama initWithFrame con un rect – drvdijk

+0

cero Me he dado cuenta ahora, mientras se aplica una transformación a una vista, la se llama a layoutSubviews. Teniendo en cuenta que estoy aplicando la transformación en el método touchesMoved de la controladora de vista, no sería recomendable realizar mucho trabajo en layoutSubviews ... – drvdijk

+1

'layoutSubviews' se llama perezosamente (después de' setNeedsLayout') y solo una vez por un montón de cambios . Por lo tanto, es el mejor lugar para realizar costosos redimensionamientos. –

0

Actualmente estoy tratando de lograr lo mismo después de la subclasificación de UIViewController para crear un componente genérico y llegó a notar algo bastante raro:

UIViewController tiene un método "loadView" que puede anular a (citando la documentación) "Aquí es donde las subclases deberían crear su jerarquía de vista personalizada".

Por lo tanto, creo mi jerarquía de vista, componiendo mi pantalla usando un tamaño de fotograma predeterminado (ya que puede que no sepa en qué marco debería mostrar cosas en el momento en que se llama a loadView).

Pero entonces, ¿en qué llamada configuro correctamente los tamaños de fotograma? Aka: ¿a qué hora mi controlador de vista está al tanto de su tamaño real?

¿Tengo que crear un "setFrame" en mi subclase ViewController que el objeto que crea el viewcontroller debería llamar? eso parece extraño

drvdijk: ¿tiene usted una solución a su problema?

EDIT: acaba de encontrar esta nota en la documentación UIViewController: Nota: No debe usar los controladores de vista para gestionar vistas que llenan sólo una parte de su ventana, es decir, sólo una parte de la zona definida por el rectángulo contenido de la aplicación. Si desea tener una interfaz compuesta por varias vistas más pequeñas, incrústelas todas en una sola vista de raíz y administre esa vista con su controlador de vista.

Parece que la vista principal de UIViewController es siempre a pantalla completa. Período.

Eso sí que me plantea un problema, ya que estoy tratando de crear un UITabBarViewController personalizado (para poder mostrar imágenes personalizadas en la barra de pestañas, y no en azul): mi tabBarViewController debería mostrar subviewcontrollers en una parte de solo la ventana ...

+5

_italic_No debe usar los controladores de vista para administrar las vistas que llenan ..._ italic_ Esto proviene de la documentación de MONO, NO de Apple, y es incorrecto. – damian

+0

Parece que Apple cambió esa parte de la documentación (la actualizan de manera regular) cuando la mencioné. En una nota lateral, siempre que hayas encontrado esa parte en algún doc. Mono (cosa que no hice): dudo mucho que Mono haya decidido inventar esta regla por sí mismo. Debieron haber elegido una versión anterior del Apple Doc y guardarla. –

+0

hmm, hace mucho tiempo, podría ser así :-) – damian

0

Es posible que desee calcular los límites del espacio de pantalla disponible (que depende de la presencia de otras vistas como barra de navegación, barra de pestañas y barra de estado). Puede usar estos límites para el parámetro de cuadro en [[UIView alloc] initWithFrame:] en loadView.

Si esto es lo que quieres, entonces usted puede encontrar mi respuesta aquí útiles: Determine the correct size in loadView

Cuestiones relacionadas