简体   繁体   English

iOS模糊文本:一劳永逸地检测和解决它?

[英]iOS blurred text: detecting & solving it once and for all?

More than once I've encountered the situation where a UIView (subclass) ends up on a fractional offset, eg because its dimensions are odd and it's centered, or because its location is based on the center of an odd-sized container. 不止一次,我遇到过UIView(子类)以小数偏移结束的情况,例如因为它的尺寸是奇数并且它是居中的,或者因为它的位置是基于奇数大小的容器的中心。

This results in blurred text (or images), because iOS will try to render the view (and subviews) on half-pixel offsets. 这会导致文本(或图像)模糊,因为iOS会尝试在半像素偏移上渲染视图(和子视图)。 I feel that calling CGRectIntegral() for every frame-change is not a perfect solution. 我觉得为每个帧更改调用CGRectIntegral()并不是一个完美的解决方案。

I'm looking for the best way to detect those situations easily. 我正在寻找轻松检测这些情况的最佳方法。 While writing this question I came up with quite a drastic approach, which revealed more off-by-½'s in my current project than I could imagine. 在写这个问题时,我想出了一个非常激烈的方法,在我当前的项目中揭示了比我想象的更多的½。

So this is for sharing. 所以这是为了分享。 Comments and suggestions for better or less drastic alternatives are more than welcome. 对于更好或更少激烈的替代品的评论和建议非常受欢迎。

main.m 的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 UIViewOverride.m

This is implemented as a UIView subclass, which avoids casts and/or compiler warnings. 这是作为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

Problematic views will generate log messages and turn up transparent and either red or green. 有问题的视图将生成日志消息并变为透明的红色或绿色。

-DDEBUGVIEW to be set as compiler flag in Debug mode. -DDEBUGVIEW在调试模式下设置为编译器标志。

您可以通过CoreAnimation仪器及其未对齐标记获得相同的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM