UIView contentScaleFactor depends on the implementation of drawRect :?

I came across a strange thing. It looks like the UIView contentScaleFactor always 1, even on Retina devices, unless you implement drawRect: Consider this code:

 @interface MyView : UIView @end @implementation MyView - (id) initWithFrame: (CGRect) frame { self = [super initWithFrame: frame]; if (self) { NSLog(@"%s %g %g %g", __PRETTY_FUNCTION__, self.contentScaleFactor, self.layer.contentsScale, [UIScreen mainScreen].scale); } return self; } - (void) didMoveToWindow { if (self.window) NSLog(@"%s %g %g %g", __PRETTY_FUNCTION__, self.contentScaleFactor, self.layer.contentsScale, [UIScreen mainScreen].scale); } @end 

On a Retina device, it prints the following:

 -[MyView initWithFrame:] 1 1 2 -[MyView didMoveToWindow] 1 1 2 

If I add an empty drawRect: implementation as follows:

 - (void) drawRect: (CGRect) rect { } 

works as expected:

 -[MyView initWithFrame:] 2 2 2 -[MyView didMoveToWindow] 2 2 2 

So it looks like it doesn't matter if there is a view in any hierarchy of views and on what screen it is displayed. The only thing that matters is that the view implements drawRect: or not.

Is this a bug or function? I know that I can change didMoveToWindow as shown below to fix it

 - (void) didMoveToWindow { if (self.window) self.contentScaleFactor = self.window.screen.scale; } 

but the default behavior is still bothering me.

You may ask why I need a contentScaleFactor at all if I am not drawing anything. This is because I just set self.layer.contents to the finished image, and then stretched the image using contentStretch . However, the image does not stretch properly on Retina devices if the contentScaleFactor not set correctly, even if the @2x image is used. To be precise, it works correctly if the @2x image is not used. This, I think, is a mistake.

Can someone share their understanding of why contentScaleFactor behaves this way? Is this specific to iOS 5 only?

+7
source share
2 answers

Presumably, if you do not override drawRect: then UIKit knows that a UIView does not draw anything, therefore a (presumably) quick case of having a layer with content scale 1 is required. As soon as you redefine drawRect: although it knows what it needs to configure a layer with the correct content scale, which you can paste into if you want. He does not know that you are not doing anything in drawRect: although he cannot make the same assumption as before.

Virtually everything mentioned in the docs:

For views that implement their own drawRect: method and are associated with a window, the default value for this property is the scale factor associated with the screen currently displaying the view.

Why don't you just override drawRect: and in this, draw an image? Or you could get away from what you are doing now and have a drawRect: stub. Considering what the documents say, I would say that it is quite reasonable to assume that he will continue to work and will be the right behavior.

+10
source

Natural drawing technologies such as Core Graphics take into account the current scale factor for you. For example, if one of your views implements the drawRect: method, UIKit automatically sets the scale factor for this view to the screen zoom factor. In addition, UIKit automatically changes the current transformation matrix of any graphic contexts used during drawing to take into account the scale factor of the view. Thus, any content that you draw in the drawRect: method scales accordingly for the screen of the main devices.

0
source

All Articles