title: iOS blurred text: detecting & solving it once and for all?
body: <p>More than once I've encountered the situation where a UIView (subclass) ends up on a fractional offset, e.g. because its dimensions are odd and it's centered, or because its location is based on the center of an odd-sized container.</p>
  
  <p>This results in blurred text (or images), because iOS will try to render the view (and subviews) on half-pixel offsets. I feel that calling <code>CGRectIntegral()</code> for every frame-change is not a perfect solution.</p>
  
  <p>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.</p>
  
  <p>So this is for sharing. Comments and suggestions for better or less drastic alternatives are more than welcome.</p>
  
  <h2>main.m</h2>
  
  <pre><code>#import &lt;objc/runtime.h&gt;
  #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
  </code></pre>
  
  <h2>UIViewOverride.m</h2>
  
  <p>This is implemented as a UIView subclass, which avoids casts and/or compiler warnings.</p>
  
  <pre><code>#define FRACTIONAL(f) (fabs(f)-floor(fabs(f))&gt;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
  </code></pre>
  
  <p>Problematic views will generate log messages and turn up transparent and either red or green.</p>
  
  <p><code>-DDEBUGVIEW</code> to be set as compiler flag in Debug mode.</p>