UIView的contentScaleFactor依赖于实现drawRect:?

时间:2012-02-28 09:01:17

标签: ios uiview retina-display

我偶然发现了一件奇怪的事情。看起来UIView的{​​{1}}始终为1,即使在Retina设备上也是如此,除非您实施contentScaleFactor。请考虑以下代码:

drawRect:

在Retina设备上,它会打印以下内容:

@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

如果我像这样添加-[MyView initWithFrame:] 1 1 2 -[MyView didMoveToWindow] 1 1 2 的空实现:

drawRect:

它按预期工作:

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

因此,如果视图位于任何视图层次结构中以及它显示在哪种屏幕上,那么看起来并不重要。唯一重要的是视图是否实现-[MyView initWithFrame:] 2 2 2 -[MyView didMoveToWindow] 2 2 2

这是一个错误还是一个功能?我知道我可以更改drawRect:,如下所示来修复它

didMoveToWindow

但默认行为仍然让我感到困扰。

如果我不画任何东西,你可能会问我为什么需要- (void) didMoveToWindow { if (self.window) self.contentScaleFactor = self.window.screen.scale; } 。那是因为我只是将contentScaleFactor设置为现成的图像,然后使用self.layer.contents拉伸图像。但是,即使使用contentStretch图像,除非contentScaleFactor设置正确,否则图像在Retina设备上无法正确拉伸。确切地说,它正常工作除非使用@2x图像。我猜这是一个错误。

任何人都可以分享您对@2x行为方式的看法吗?它仅适用于iOS 5吗?

2 个答案:

答案 0 :(得分:10)

据推测,如果你不重写drawRect:,那么UIKit就知道UIView没有绘制任何东西,所以它需要(可能)快速的情况下拥有一个层内容比例为1.但是,只要覆盖drawRect:,它就知道需要设置一个具有正确内容比例的图层,如果您愿意,可以将其绘制。它并不知道你在drawRect:中什么都不做,但它不能像以前那样做出相同的假设。

事实上,文档中提到了所有这些:

  

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

为什么不覆盖drawRect:并在其中绘制图像?或者你可能会逃脱你当前正在做的事情并拥有一个存根drawRect:。鉴于文档所说的内容,我可以说假设它会继续工作并且是正确的行为是完全合理的。

答案 1 :(得分:0)

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