UIView的contentScaleFactor依赖于实现drawRect:?

我偶然发现了一件奇怪的事情。 它看起来像UIViewcontentScaleFactor始终是1,即使在Retina设备,除非你实现drawRect: 考虑这个代码:

 @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 

在Retina设备上打印下列内容:

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

如果我添加一个空的drawRect:实现drawRect:像这样:

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

它按预期工作:

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

所以看起来好像这个视图是否在任何视图层次结构中,以及它显示的是什么样的屏幕并不重要。 唯一重要的是如果视图实现drawRect:或不。

这是一个错误或function? 我知道我可以改变didMoveToWindow如下来解决它

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

但默认行为仍然错误我。

如果我没有画任何东西,你可能会问为什么我需要contentScaleFactor 。 这是因为我只是将self.layer.contents设置为现成的图像,然后使用contentStretch拉伸图像。 但是,除非使用了@2x图像,否则图像无法在Retina设备上正常展开,除非contentScaleFactor设置正确。 确切地说, 除非使用@2x图像, 否则它可以正常工作。 我想这是一个错误。

任何人都可以分享你的见解,为什么contentScaleFactor行为? 仅针对iOS 5吗?

据推测,如果你不重写drawRect:那么UIKit知道一个UIView不会绘制任何东西,所以它需要一个内容比例为1的图层(假定)。只要你重写drawRect:尽pipe,它知道需要设置一个正确的内容比例的图层,如果你愿意的话可以绘制成图层。 它并不知道你在drawRect:什么都不做drawRect:尽pipe如此,它不能和以前一样。

事实上,在文档中提到了这一切:

对于实现自定义drawRect:方法并与窗口关联的视图,此属性的默认值是与当前显示视图的屏幕相关联的比例因子。

你为什么不重写drawRect:在那里画图片? 或者你也许可以逃避你正在做的事情,并有一个存根。 根据文档的说法,我认为这是完全合理的假设它将继续工作,是正确的行为。

原生绘图技术(如Core Graphics)会考虑当前的比例因子。 例如,如果其中一个视图实现了drawRect:方法,则UIKit会自动将该视图的比例因子设置为屏幕的比例因子。 此外,UIKit会自动修改绘图过程中使用的任何graphics上下文的当前转换matrix,以考虑视图的比例因子。 因此,您在drawRect:方法中绘制的任何内容都会针对底层设备的屏幕进行适当缩放。