首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CATiledLayer如何在内部工作

CATiledLayer如何在内部工作
EN

Stack Overflow用户
提问于 2018-05-09 19:52:17
回答 1查看 440关注 0票数 1

我是iOS开发的新手,我正在努力弄清楚CATiledLayer是如何工作的。而不是如何使用它!

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

  1. 可见边界自动报告。CATiledLayer如何知道它的可见边界已经改变了?我可以创建一个自定义的CALayer并注册以知道相同的信息吗?
  2. 瓷砖绘图这些瓷砖是怎么画的?它们是分层画的吗?

我想了解这两个关键点是如何工作的原因是,我正在构建一个可以具有非常大宽度的自定义UIView,而CALayer会因为有这么大的后台层而崩溃。CATiledLayer有一个轻的内存使用和它‘几乎完美!

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

只是想多加一点。我正在构建一个音频编辑器,它显示音频波形,用户可以调整这个剪辑的大小。剪辑显示在集合视图中。以上提到的问题与CATiledLayer似乎是相同的问题车库乐队。我几乎没有注意到,当调整一个音频剪辑的左边。他们可能使用CATiledLayer

EN

回答 1

Stack Overflow用户

发布于 2018-05-10 02:59:49

我知道一种解决第一问题的方法,但我不确定结果和效率。这是更多的理论,但它是可行的。我使用一个CADisplayLink来运行一个检查,看看该层的帧是否在主窗口中。我确实注意到使用了少量的CPU (1%或更少),所以与CATiledLayer相比,我会更多地测试它。CATiledLayer只是中断了绘图,但在相同的前提下操作,即只能绘制可见的内容。我认为,当可见或可见边界发生变化时,drawRect从根本上起作用。至于我测试的子类,我在UICollectionView中使用了它,并且知道它可以工作。我甚至可以获得创建单元格的记录,而不是屏幕上的日志。下面是CALayer的工作子类。我不知道这是否对你有帮助,但这是可能的。

代码语言:javascript
复制
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可能不使用子层,而是将所有内容缓慢地绘制到一个内容图像中,而是通过平铺和可能更简单的数学计算。它可能是将可见区域绘制在背景中并提供层内容的东西。然后缓存该部分并添加另一个部分,直到它是complete.This,这只是猜测。

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

代码语言:javascript
复制
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中设置的,所以我可以监视它。如果这有帮助的话请告诉我。此外,检查还可以修改框架,以便在它出现在屏幕上之前以一条空白的方式捕捉它,即在此之前绘制的方式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50261060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档