Я неоднократно сталкивался с ситуацией, когда UIView (подкласс) заканчивается дробным смещением , например, потому что его размеры нечетные и он центрирован, или потому, что его местоположение основано на центре контейнера нечетного размера.
Это приводит к размытому тексту (или изображениям), потому что iOS будет пытаться визуализировать представление (и подпредставления) со смещением на полпикселя. Я считаю, что вызов CGRectIntegral ()
для каждой смены кадра не является идеальным решением.
Я ищу лучший способ легко обнаруживать такие ситуации. При написании этого вопроса я пришел к довольно радикальному подходу, который выявил в моем текущем проекте больше отклонений на 1/2, чем я мог себе представить.
Так что это для того, чтобы поделиться. Комментарии и предложения по лучшим или менее радикальным альтернативам более чем приветствуются.
#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
Это реализовано как подкласс 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
должен быть установлен как флаг компилятора в режиме отладки.