[iOS]CALayerの基本概念


1.UIViewとCALayer(最下位)の関係


  • UIViewを継承するViewクラスがインスタンス化されるとCaLayerがインスタンス化されます.これは,UIViewクラスがCaLayer Delegateを採用しているためである.したがって、各ビューにはレイヤがあります.

  • 実際、UIVEewは自分で描くのではなく、レイヤーに描くのです.view.backgroundColorの変更も実際にはlayerのbackgroundColorを変更し、逆にlayerのbackgroundColorを変更するとviewに反映されます.同様にviewのframeは事実層のframeである.すなわち、すべてのビューの描画はlayerで完了します.

  • 実際には、ビューのほとんどのプロパティには、アクセスレイヤのプロパティの役割があります.viewはlayerの「エージェント(delegate)」だからです.
  • 2.layerを利用する方法


  • Layerがdrawingで提供する属性はUIViewの属性よりずっと多い.すなわち、レイヤーにアクセスするプロパティは、ビューを描画するための多くのオプションを管理することができます.

  • Layerは、他のlayers(サブlayers)を含むことができる.これにより、UIViewを複数の部分に分割することができ、各部分をobjectと見なし、図面をより効率的に管理することができる.1つの部分として管理されるviewを複数の部分に分解して描画とマージします.

  • layerを使用すると、アニメーション効果を制御できます.CALayerの「CA」はCore Animationの略です.つまり、アニメを征服するためにはCaLayerを征服しなければならない.
  • 3.Bitmapキャッシュを使用したビュー描画の管理-オンデマンド描画


  • viewは再描画を最大限に防ぐことができます.これは仕事の効率を高めるためです.この目的で使用されるのは、ビットマップバックアップストレージです.ビューがレイヤに描画されると、レイヤはビューをキャッシュし、マップキャッシュに保存して再使用します.viewの境界が変更されると、キャッシュレイヤ内の画像が展開または再配置されるように再使用されます.

  • ビューに表示される内容を変更してredrawを行う場合はsetNeedsDisplay()メソッドを呼び出します.setNeedsDisplay()を呼び出すと、キャッシュが削除され、REDOの結果が再キャッシュされます.

  • Content ModeのScale to Fill、Asspecti Fit、およびAsspect Fillは、ビットマップキャッシュを使用します.

  • 4.カスタムCALayerの使い方

  • のデフォルトでは、UIViewインスタンス化時に一緒にインスタンス化されるのがvanila CaLayerです.使用したくないのではなく、カスタムlayerを使用したい場合があります.このため、以下の方法を使用して、UIViewのサブクラスでLayer Class PropertyをCaLayerサブクラスに戻すことができます.
  • class SomeView: UIView {
       override class var layerClass: AnyClass {
            return CustomLayer.self
       }
    }

    5.サブレイヤーとレイヤーの階層

  • 層は、複数のサブ層があってもよいし、1つのスーパー層があってもよい.すなわち,viewのようにlayerも階層を考慮できる.実際、viewとlayerの関係は非常に緊密であるため、viewの階層はlayerの階層と実際には同じであると考えることができます.より具体的には、SuperViewのlayerはSuperLayerとなり、すべてのサブビューのlayerはSubLayerとなる.常識的には、ビューがレイヤを描くため、ビューの階層はレイヤの階層のみです.(図ソース:Matt Neuburg's Programming iOS、Dive Deep to View、View Control、Frameworks)
  • ただし、大きなスケルトンが同じであっても階層が異なる場合があります.本当は変化よりも細かくviewには1つのレイヤしかないので、レイヤ自体にはビューに属さないサブレイヤがあります.下図のように.(図ソース:Matt Neuburg's Programming iOS、Dive Deep to View、View Control、Frameworks)
  • レイヤを使用すると、1つのビューを使用して複数のビューを表示できます.
  • class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let firstLayer = CALayer()
                 firstLayer.backgroundColor = UIColor.red.cgColor
                 firstLayer.frame = CGRect(x: 111, y: 111, width: 132, height: 194)
            let secondLayer = CALayer()
                 secondLayer.backgroundColor = UIColor.blue.cgColor
                 secondLayer.frame = CGRect(x: 41, y: 56, width: 132, height: 194)
            let thirdLayer = CALayer()
                 thirdLayer.backgroundColor = UIColor.green.cgColor
                 thirdLayer.frame = CGRect(x: 43, y: 197, width: 132, height: 194)
                
                self.view.layer.addSublayer(firstLayer)
                firstLayer.addSublayer(secondLayer)
                self.view.layer.addSublayer(thirdLayer)   
        }
    }    

  • 上記の例では、1つのviewと3つのlayerを用いて、下図に示す3つのviewに類似した画面を実現した.ここで、firstLayerとthirdLayerは兄弟関係であり、secondlayerはfirstLayerのサブ層である.


  • ここで新しいviewselfをビューでaddSubview()を使用すると、注意点が表示されます.この場合、サブオブジェクトをSuperViewまたはSuperLayer境界でカットするかどうかを決定すると、layerになります.MaskToBoundsビューを使用するかどうか.これは、clipsToBoundsに書き込むかどうかを区別する必要があります.Layerは必ずしもViewではありませんが、layerでなければなりません.ビューのデフォルトレイヤに画像をカットできる場合はclipsToBoundsを使用します.そうでない場合はlayerを使用する必要があります.MaskToBoundsを使用する必要があります.すなわち,ビューが存在するレイヤで動作するとviewとなる.clipsToBoundsを使っても構いませんが、Viewのないレイヤーであればlayerです.MaskToBoundsを使用する必要があります.