Texto borroso de iOS: ¿detectarlo y resolverlo de una vez por todas?

Más de una vez me he encontrado con la situación en la que una UIView (subclase) termina en un desplazamiento fraccional, por ejemplo, porque sus dimensiones son impares y está centrada, o porque su ubicación se basa en el centro de un contenedor de tamaño impar.

Esto da como resultado texto (o imágenes) borroso, porque iOS intentará representar la vista (y subvistas) en compensaciones de medio píxel. Siento esa llamada CGRectIntegral() porque cada cambio de cuadro no es una solución perfecta.

Estoy buscando la mejor forma de detectar esas situaciones fácilmente. Mientras escribía esta pregunta, se me ocurrió un enfoque bastante drástico, que reveló más desviaciones por ½ en mi proyecto actual de lo que podía imaginar.

Entonces esto es para compartir. Los comentarios y sugerencias sobre alternativas mejores o menos drásticas son más que bienvenidos.

main.m

#import <objc/runtime.h>
#import "UIViewOverride.h"

int main(int argc, char *argv[]) {

#ifdef DEBUGVIEW
    Method m1,m2;
    IMP imp;
    m1 = class_getInstanceMethod([UIView class], @selector(setFrame:));
    m2 = class_getInstanceMethod([UIViewOverride class], @selector(setFrameOverride:));
    imp = method_getImplementation(m2);
    class_addMethod([UIView class], @selector(setFrameOverride:), imp, method_getTypeEncoding(m1));
    m2 = class_getInstanceMethod([UIView class], @selector(setFrameOverride:));
    method_exchangeImplementations(m1,m2);

    m1 = class_getInstanceMethod([UIView class], @selector(setCenter:));
    m2 = class_getInstanceMethod([UIViewOverride class], @selector(setCenterOverride:));
    imp = method_getImplementation(m2);
    class_addMethod([UIView class], @selector(setCenterOverride:), imp, method_getTypeEncoding(m1));
    m2 = class_getInstanceMethod([UIView class], @selector(setCenterOverride:));
    method_exchangeImplementations(m1,m2);
#endif

// etc

UIViewOverride.m

Esto se implementa como una subclase de UIView, que evita conversiones y / o advertencias del compilador.

#define FRACTIONAL(f) (fabs(f)-floor(fabs(f))>0.01)

@implementation UIViewOverride

#ifdef DEBUGVIEW
-(void)setFrameOverride:(CGRect)newframe
{
    if ( FRACTIONAL(newframe.origin.x) || FRACTIONAL(newframe.origin.y) )
    {
        [self setBackgroundColor:[UIColor redColor]];
        [self setAlpha:0.2];
        NSLog(@"fractional offset for %@",self);
    }
    [self setFrameOverride:newframe]; // not a typo
}

-(void)setCenterOverride:(CGPoint)center
{
    [self setCenterOverride:center]; // not a typo
    if ( FRACTIONAL(self.frame.origin.x) || FRACTIONAL(self.frame.origin.y) )
    {
        [self setBackgroundColor:[UIColor greenColor]];
        [self setAlpha:0.2];
        NSLog(@"fractional via center for %@",self);
    }
}
#endif

Las vistas problemáticas generarán mensajes de registro y aparecerán transparentes y en rojo o verde.

-DDEBUGVIEW para establecerse como bandera del compilador en modo Depuración

preguntado el 09 de enero de 11 a las 03:01

1 Respuestas

Puede obtener esta misma funcionalidad a través del instrumento CoreAnimation y su indicador desalineado.

Respondido el 09 de enero de 11 a las 06:01

Fresco. Nunca había oído hablar de él antes, ¡pero definitivamente es mucho más fácil que lo que hice! - mvds

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.