Я не раз сталкивался с ситуацией, когда 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
для установки в качестве флага компилятора в режиме отладки.