Размытый текст в iOS: найти и решить его раз и навсегда? - PullRequest
5 голосов
/ 09 января 2011

Я не раз сталкивался с ситуацией, когда UIView (подкласс) оказывается с дробным смещением, например потому что его размеры нечетны и он центрирован, или потому что его местоположение основано на центре контейнера нечетного размера.

Это приводит к размытому тексту (или изображениям), потому что iOS будет пытаться визуализировать вид (и подпредставления) на полпиксельных смещениях. Я чувствую, что вызов CGRectIntegral() для каждой смены кадра - не идеальное решение.

Я ищу лучший способ легко обнаружить такие ситуации. Во время написания этого вопроса я придумал довольно радикальный подход, который выявил в моем текущем проекте больше «½», чем я мог себе представить.

Так что это для обмена. Комментарии и предложения по лучшим или менее радикальным альтернативам приветствуются.

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

Это реализовано в виде подкласса UIView, который избегает приведений и / или предупреждений компилятора.

#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

Проблемные представления генерируют сообщения журнала и становятся прозрачными и имеют красный или зеленый цвет.

-DDEBUGVIEW для установки в качестве флага компилятора в режиме отладки.

1 Ответ

8 голосов
/ 09 января 2011

Вы можете получить эту же функциональность с помощью инструмента CoreAnimation и его флага со смещением.

...