Here is a simple drawing
- (void)drawRect:(CGRect)rect
{
//vertical line with 1 px stroking
UIBezierPath *vertLine = [[UIBezierPath alloc] init];
The reason you get different results with stroke and fill is that their interpretations of arguments is different.
Stroke adds half the width of the line at each side of the coordinate. So, your point is 20.0 and width of line is 1px. The result will be a 1 pixel black line between (19.5-20.5), theorically. Since there isn't any nonintegral pixel on the device screen, it will be converted 2 pixels gray/blurry line between (19-21). to circumvent this, you need to sum each of your coordinates with 0.5 (as in CGPointMake(20.5, 10.5) ) so that width won't be divided between pixels any longer.
However, the arguments in the fill are used to set the borders of the region to fill, CGRectMake(40.0, 10.0, 1.0, 390.0) implies a region between (40 - 41). As a result there is no fractional part falling on the pixels to look blurry.