iOS 12,Xcode 10:UIView setNeedsDisplay(_ :)似乎被打破了

问题描述 投票:2回答:2

更新到Xcode 10后,我意识到我的应用程序中的自定义UIView(来自UIView的类)的draw(_ rect: CGRect)例程被调用了错误的rect。实际上它总是被称为rect是底层UIView的完整框架,而不是由rect指定的setNeedsDisplay(_ rect: CGRect)

这是一个可以作为游乐场运行的代码段,至少在我的设置中,它在简约设置中显示了上述错误行为:

import Foundation
import UIKit
import PlaygroundSupport

class CustomView: UIView {
    override func draw(_ rect: CGRect) {
        print("rect = \(rect)")
    }
}

let customView = CustomView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 200.0, height: 200.0)))
PlaygroundPage.current.liveView = customView
print("test")
customView.setNeedsDisplay(CGRect(origin: CGPoint.zero, size: CGSize(width: 100.0, height: 100.0)))

我得到的输出是

rect =(0.0,0.0,200.0,200.0) 测试 rect =(0.0,0.0,200.0,200.0)

rect的第一个打印输出是视图的标准完全重绘,但是打印“test”后的第二个输出会产生问题。由于之前调用customView.setNeedsDisplay而导致的输出是重绘,应该是较小的指定矩形(0.0, 0.0, 100.0, 100.0)

所以我显而易见的问题是:

  • 你能重现这种行为吗?
  • 我错过了一些明显的东西吗
  • 这是一个错误吗?
ios swift xcode10 ios12
2个回答
2
投票

我在Xcode 9,10和10.1中进行了测试。

iOS 11和iOS 12 / 12.1之间的行为已经发生了明显变化

文档或头文件中没有任何迹象表明这是故意的。

对我来说看起来像个错误。


2
投票

这实际上是iOS 12的新动态后备存储功能的故意。

什么是支持商店

后备存储是存储绘制视图的内容,并且需要分配的内存来执行此操作。该内存量取决于视图的大小,因为它本质上是颜色和像素之间的映射。

如果您要绘制灰度图像,但已为宽色域指定了内存,那么将导致大量空的指定内存(灰度级具有较低的RGBA占用空间)。为了解决这个问题,动态后备存储功能通过绘制视图的整个内容来工作,然后确定它需要多少内存,而不是假设从一开始就需要广泛的颜色支持。

这样做的结果是你无法重新绘制视图的较小子部分,因为这可能会改变这个商店。

如何解决它

这是一个很棒的新功能,但如果您确实需要解决它,可以在视图上禁用动态后备存储。你这样做的方法是明确设置视图contentsFormatlayer属性。

您可以选择三种与灰度相关的选项,RGBA 8位和RGBA 16位(宽色)

所以请致电:

layer.contentsFormat = .RGBA16Float

而你的setNeedsDisplay(_ rect: CGRect)将再次按预期开始工作

您可以在这里阅读酒店:https://developer.apple.com/documentation/quartzcore/calayer/1792104-contentsformat

WWDC 18也有一个很好的演讲,解释了新的动态后备存储和(非常安静地)提到这种技术

https://developer.apple.com/videos/play/wwdc2018/219/?time=1451

© www.soinside.com 2019 - 2024. All rights reserved.