UIView的contentScaleFactor属性是否取决于实现drawRect方法?

10

我遇到了一个奇怪的问题。看起来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:实现,就像这样:
- (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拉伸图像。然而,在Retina设备上,如果没有正确设置contentScaleFactor,图像就无法正确地拉伸,即使使用了@2x图像。准确地说,它可以正常工作,除非使用@2x图像,这可能是一个错误。

有人能分享一下为什么contentScaleFactor会表现出这种方式吗? 这是否只适用于iOS 5?

2个回答

12

假设你不覆盖drawRect:,那么UIKit会知道UIView不绘制任何东西,所以它使用一个内容缩放比例为1的层(可能)快速渲染。但是一旦你覆盖了drawRect:,UIKit就知道,如果需要,它必须设置一个正确的内容缩放比例的层供你进行绘制。但是,它不知道你在drawRect:中什么都没有做,因此不能像之前那样做出相同的假设。

实际上,文档中已经提到了这一点:

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

你为什么不只是覆盖drawRect:并在其中绘制你的图像呢?或者你可能可以继续使用你目前正在做的事情,并且拥有一个存根drawRect:。根据文档内容,我认为这是合理的假设,它将继续工作并且是正确的行为。


非常感谢!本质上,我也是这么认为的,但是“对于实现自定义drawRect:方法并且与窗口相关联的视图”(强调我的)意味着只有在将视图添加到窗口后才能做出决定。正如您所看到的,被忽略的是与窗口的关联。也许只是文档错误。至于在drawRect:中绘制,我避免这样做,因为视图非常大,而且我有十几个这样的视图,而我正在拉伸的图像是31x31像素。基本上,我只是尽可能地保持内存占用量低。 - Costique
谢谢。我一直在使用自定义CALayer进行绘图,但它的contentScale总是被重置为1。现在它看起来非常清晰。 - Glenn Howes

2

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接