gpt4 book ai didi

ios - CATiledLayer 内部是如何工作的

转载 作者:行者123 更新时间:2023-11-29 11:34:53 24 4
gpt4 key购买 nike

我是 iOS 开发的新手,我正在尝试了解 CATiledLayer 的工作原理。不是如何使用它!

CATiledLayer 有两个关键特性,我想知道它是如何工作的。

  1. 可见范围自动报告。 CATiledLayer 如何知道它的可见边界已经改变?我可以创建自定义 CALayer 并注册以了解相同的信息吗?

  2. 瓷砖绘图。这些瓷砖是如何绘制的?它们是作为子层绘制的吗?

我想知道这两个关键点是如何工作的原因是我正在构建一个自定义 UIView,它可以有一个非常大的宽度和一个 CALayer 将由于有这么大的支持层而崩溃。 CATiledLayer 内存使用率低,几乎是完美的!

我不想使用 CATiledLayer 的原因是它的内部工作方式。所有绘图都发生在后台线程上。我知道您甚至可以在主线程上调用绘图逻辑,但这会在下一个绘图周期发生。由于绘图不会在同一个绘图周期中发生,因此在 View 调整大小时,我们的绘图逻辑会延迟更新绘图,从而导致 UIView 内容在用户更新期间发生抖动。

再补充一点。我正在构建一个音频编辑器,它可以显示音频波形,用户可以调整该剪辑的大小。该剪辑显示在 Collection View 中。上面提到的 CATiledLayer 问题似乎与 Garage band 的问题相同。在向左调整音频剪辑大小时,我几乎没有注意到它。他们可能正在使用 CATiledLayer

最佳答案

我知道一种解决第一个问题的方法,但我不确定结果和效率。除了它有效之外,这更具理论性。我正在使用 CADisplayLink 运行检查以查看图层的框架是否在主窗口中。我确实注意到使用了少量 CPU(1% 或更少),因此与 CATiledLayer 相比,我会对其进行更多测试。 CATiledLayer 只是打破了绘图,但在同样的前提下运行,即只有可见的才能被绘制。 drawRect 我认为在可见或可见边界发生变化时基本上起作用。至于我测试的子类,我在 UICollectionView 中使用了它并且知道它可以工作。我什至可以获得单元格创建时间的日志,而不是在屏幕上。这是 CALayer 的工作子类。我不知道这是否对您有帮助,但这是可能的。

import UIKit
protocol OnScreenLayerDelegate:class {
func layerIsOnScreen(currentScreenSpace:CGRect)
func layerIsNotOnScreen(currentScreenSpace:CGRect)
}
class OnScreenLayer: CALayer {

var displayLink : CADisplayLink?
weak var onScreenDelegate : OnScreenLayerDelegate?
override init() {
super.init()
commonSetup()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonSetup()
}

func commonSetup(){
displayLink = CADisplayLink(target: self, selector: #selector(checkOnScreen))
displayLink?.add(to: .main, forMode: .commonModes)
}

@objc func checkOnScreen(){
if let window = UIApplication.shared.keyWindow{
let currentRect = self.convert(self.bounds, to: window.layer)
if window.bounds.intersects(currentRect){
onScreenDelegate?.layerIsOnScreen(currentScreenSpace: currentRect)
}else{
onScreenDelegate?.layerIsNotOnScreen(currentScreenSpace: currentRect)
}
}
}
}

关于问题 2,我认为 CATiledLayers 可能不使用子层,而是慢慢地将所有内容绘制到单个内容图像中,但通过平铺和可能更容易的数学运算。它可能是将可见区域绘制在背景中并提供图层内容的东西。然后缓存该部分并添加另一个部分直到它完成。这只是一个猜测。

这是我在 collectionView 单元格中测试的代码。

import UIKit

class AlbumCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var imageView: UIImageView!
var onScreenLayer = OnScreenLayer()
var currentIndex : Int = 0
override func awakeFromNib() {
super.awakeFromNib()
onScreenLayer.frame = self.bounds
self.layer.addSublayer(onScreenLayer)
onScreenLayer.onScreenDelegate = self
}

override func layoutSubviews() {
super.layoutSubviews()
onScreenLayer.frame = self.bounds
}
}

extension AlbumCollectionViewCell : OnScreenLayerDelegate{
func layerIsOnScreen(currentScreenSpace: CGRect) {
//or more proof
print("it is on screen \(currentIndex)")

}

func layerIsNotOnScreen(currentScreenSpace: CGRect) {
print("not on screen \(currentIndex)")
}
}

当前索引是在 cellForItem 中设置的,因此我可以监视它。让我知道这是否有帮助。此外,检查可以修改框架以在它出现在屏幕上之前以您之前绘制的方式捕捉它。

关于ios - CATiledLayer 内部是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50261060/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com