2012-02-28 6 views
7

He tropezado con algo extraño. Parece que UIView 's contentScaleFactor es siempre 1, incluso en dispositivos Retina, a menos que implemente drawRect:. Considere este código:El contenido de UIViewScaleFactor depende de la implementación de drawRect :?

@interface MyView : UIView 
@end 

@implementation MyView 

- (id) initWithFrame: (CGRect) frame 
{ 
    self = [super initWithFrame: frame]; 
    if (self) { 
     NSLog(@"%s %g %g %g", __PRETTY_FUNCTION__, self.contentScaleFactor, self.layer.contentsScale, [UIScreen mainScreen].scale); 
    } 
    return self; 
} 

- (void) didMoveToWindow 
{ 
    if (self.window) 
     NSLog(@"%s %g %g %g", __PRETTY_FUNCTION__, self.contentScaleFactor, self.layer.contentsScale, [UIScreen mainScreen].scale); 
} 

@end 

En un dispositivo de Retina se imprime el siguiente:

-[MyView initWithFrame:] 1 1 2 
-[MyView didMoveToWindow] 1 1 2 

Si añado una implementación vacía de drawRect: así:

- (void) drawRect: (CGRect) rect 
{ 
} 

funciona como se esperaba:

-[MyView initWithFrame:] 2 2 2 
-[MyView didMoveToWindow] 2 2 2 

Parece que realmente no importa si la vista está en cualquier jerarquía de vistas y en qué tipo de pantalla se muestra. Lo único que importa es si la vista implementa drawRect: o no.

¿Eso es un error o de una pieza? Sé que puedo cambiar didMoveToWindow como abajo para fijarlo

- (void) didMoveToWindow 
{ 
    if (self.window) 
     self.contentScaleFactor = self.window.screen.scale; 
} 

pero el comportamiento predeterminado todavía me molesta.

Usted puede preguntar por qué necesito contentScaleFactor en absoluto si no dibujo nada. Eso es porque acabo de establecer self.layer.contents en una imagen ya hecha y luego estirar la imagen con contentStretch. Sin embargo, la imagen no se estira correctamente en dispositivos Retina a menos que contentScaleFactor esté configurado correctamente, aunque se utiliza una imagen @2x. Para ser precisos, funciona correctamente a menos se utiliza una imagen de @2x. Esto es, supongo, un error.

¿Alguien puede compartir su información sobre por qué contentScaleFactor comporta de esta manera? ¿Es específico para iOS 5 solamente?

Respuesta

10

Es de suponer que, si no se sobreescribe drawRect: continuación UIKit sabe que un UIView no dibuja nada por lo que toma la (presumiblemente) caso rápido de tener una capa que tiene una escala de contenidos 1. Tan pronto como se reemplaza drawRect:, sabe que necesita configurar una capa que sea de la escala de contenido correcta que puede dibujar si lo desea. No sabe que no hace nada en drawRect:, por lo que no puede hacer la misma suposición que antes.

De hecho todo lo que se alude en los documentos:

Para las vistas que implementan una drawRect personalizado: método y están asociados con una ventana, el valor predeterminado de esta propiedad es el factor de escala asociadas con la pantalla que muestra actualmente la vista.

¿Por qué no acaba de anular drawRect: y en eso, dibuje su imagen? O probablemente podrías salirte con la tuya y tener un stub drawRect:. Teniendo en cuenta lo que dicen los documentos, diría que es perfectamente razonable suponer que va a seguir funcionando y es un comportamiento correcto.

+0

¡Muchas gracias! En esencia, yo también lo pensé, pero "para las vistas que implementan un método' drawRect: 'personalizado y ** están asociadas a una ventana **" (énfasis mío) implica que la decisión puede tomarse solo después de agregar la vista a un ventana. Como puede ver, es una asociación con una ventana que se ignora. Tal vez solo un error de documentación. En cuanto a dibujar en 'drawRect:', lo evito porque la vista es muy grande, y tengo una docena de ellos, mientras que la imagen que estoy estirando es de 31x31 píxeles. Básicamente, estoy tratando de mantener la huella de memoria lo más bajo posible. – Costique

+0

Gracias. Estaba haciendo todo mi dibujo en un CALayer personalizado y siempre estaba restaurando su contenidoScale a 1. Ahora se ve hermosamente retina. –

0

Las tecnologías de dibujo nativas, como Core Graphics, tienen en cuenta el factor de escala actual. Por ejemplo, si una de sus vistas implementa un método drawRect:, UIKit establece automáticamente el factor de escala para esa vista en el factor de escala de la pantalla. Además, UIKit modifica automáticamente la matriz de transformación actual de los contextos gráficos utilizados durante el dibujo para tener en cuenta el factor de escala de la vista. Por lo tanto, cualquier contenido que dibuje en su método drawRect: se escala apropiadamente para la pantalla del dispositivo subyacente.

Cuestiones relacionadas