UIView的contentScaleFactor依赖于实现drawRect:? [英] UIView's contentScaleFactor depends on implementing drawRect:?

查看:125
本文介绍了UIView的contentScaleFactor依赖于实现drawRect:?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我偶然发现了一件奇怪的事情。它看起来像 UIView contentScaleFactor 总是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);
}
返回自我;
}

- (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 拉伸图像。但是,除非 contentScaleFactor 设置正确,否则图像在Retina设备上无法正确拉伸,即使 @ 2x 图像用来。确切地说,它正常工作除非使用 @ 2x 图像。我想这是一个错误。



任何人都可以分享您对 contentScaleFactor 这样做的原因的见解吗?它仅适用于iOS 5吗?

解决方案

大概,如果你不覆盖 drawRect:然后UIKit知道 UIView 没有绘制任何东西,所以它需要(大概)快速的情况下,拥有一个内容规模为1的图层一旦你覆盖 drawRect:,它就知道它需要设置一个具有正确内容比例的图层,如果你愿意,你可以绘制它。它不知道你在 drawRect:中什么都不做,但它不能做出和以前一样的假设。



事实上,文档中提到了所有内容:


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


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


I have stumbled on a weird thing. It looks like UIView's contentScaleFactor is 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 implementation of drawRect: like this:

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

it works as expected:

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

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

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

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

but the default behavior still bugs me.

You may ask why I need contentScaleFactor at all if I don't draw anything. That's because I just set self.layer.contents to a ready-made image and then stretch the image with contentStretch. However, the image doesn't stretch properly on Retina devices unless contentScaleFactor is set correctly, even though a @2x image is used. To be precise, it works correctly unless a @2x image is used. This is, I guess, a bug.

Can anyone share your insight into why contentScaleFactor behaves this way? Is it specific to iOS 5 only?

解决方案

Presumably, if you don't override drawRect: then UIKit knows that a UIView doesn't draw anything so it takes the (presumably) fast case of having a layer that has a content scale of 1. As soon as you override drawRect: though, it knows it needs to set up a layer that is of the correct content scale that you can draw into if you want to. It doesn't know that you do nothing in drawRect: though so it can't make the same assumption as before.

In fact all that is alluded to in the docs:

For views that implement a custom 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 that, draw your image? Or you could probably get away with what you're currently doing and have a stub drawRect:. Given what the docs say, I'd say that's perfectly reasonable to assume it's going to continue to work and is correct behaviour.

这篇关于UIView的contentScaleFactor依赖于实现drawRect:?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆