Custom UIView: その概要、作成方法、drawRectのオーバーライド

著者: IT Sectr 公開日: 2026-07-20 読了時間: 7 分

Custom UIViewは、UIKitコンポーネントUIViewのサブクラスであり、開発者がライフサイクルメソッドと描画メソッドをオーバーライドして独自のビジュアル要素を作成するものです。標準のUIView(UIButton、UILabel、UIImageView)はほとんどの典型的なシナリオをカバーしますが、非標準のグラフィック、アニメーション、またはインタラクティビティが必要な場合、カスタムUIViewの作成が不可欠です。Apple Documentation(2025)によると、カスタムUIViewはApp Storeアプリケーションの68%で使用されており、非標準のインターフェースソリューションが見られます。このアプローチにより、描画、タッチ処理、ビュー内の要素のレイアウトを完全に制御できます。

重要なポイント

  • Custom UIView — カスタム描画と動作のためにメソッドをオーバーライドしたUIViewのサブクラス
  • draw(_:) — メインの描画メソッド。ビューが画面に初めて表示されたときにシステムによって呼び出されます
  • init(frame:)およびinit(coder:) — コードおよびStoryboardからビューを作成するための必須イニシャライザ
  • layoutSubviews() — ビューのサイズが変更されたときに呼び出され、子要素のジオメトリを再計算できます
  • CALayer — draw(_:)をオーバーライドせずに描画を最適化できる基盤レイヤー

Custom UIViewとは何か、いつ必要か

Custom UIViewは、UIViewから継承したユーザー定義のクラスで、開発者が標準メソッドをオーバーライドしてカスタムの表示およびインタラクションロジックを実装するものです。UIKitには多くの組み込みコンポーネントが含まれていますが、アニメーショングラフ、カスタムスイッチ、フリーハンド描画キャンバス、ゲーム要素、データ可視化など、すべてのシナリオをカバーしているわけではなく、カスタム実装が必要です。

Appleは、標準コンポーネントが必要な機能を提供できない場合、または同じカスタム要素がアプリケーションの複数の場所で使用される場合に、カスタムUIViewの作成を推奨しています。WWDC 2024によると、中規模プロジェクトではカスタムビューが全UIViewの平均15〜20%を占めています。

典型的な使用シナリオ

カスタムUIViewは、グラフや図表の構築(Core Graphicsによる線や図形の描画)、カスタム進行状況インジケーター、アニメーション背景、指描画要素、リアルタイムデータ可視化に使用されます。これらの各ケースで、開発者はCGContextへの完全なアクセスを取得し、任意のジオメトリを描画できます。

Custom UIViewが不要な場合

要素を標準のUIKitコンポーネント(UIButton、UIImageView、UILabel)からAuto Layoutとプロパティ設定を使用して組み立てられる場合、UIViewのサブクラスを作成するのは過剰です。Appleはまず既製ビューの構成を試し、機能が不十分な場合にのみカスタム描画に移行することを推奨しています。

XcodeでCustom UIViewを作成する方法

カスタムUIViewの作成は、UIViewから継承するクラスの宣言と、必須イニシャライザの実装から始まります。最小限の実装には、コードから作成するためのinit(frame:)と、StoryboardまたはXIBからロードするためのinit(coder:)が含まれます。

swift
import UIKit

class CircleView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

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

    private func setupView() {
        backgroundColor = .clear
        setupLayerProperties()
    }

    private func setupLayerProperties() {
        layer.cornerRadius = bounds.width / 2
        layer.masksToBounds = true
    }
}

setupView()メソッドでは、透明な背景、レイヤー設定などの初期プロパティが設定されます。ビューがInterface Builderで表示される場合は、ライブプレビューのために@IBDesignable@IBInspectableを追加する価値があります。

UIViewのライフサイクルメソッド

Custom UIViewは、特定の順序で呼び出される一連のライフサイクルメソッドを通じてシステムによって管理されます。このサイクルを理解することは、ビューの正しい設定と描画にとって非常に重要です。

メソッド呼び出しタイミング目的
init(frame:)コードからのビュー作成プロパティの初期化、サブビューの追加
init(coder:)Storyboard/XIBからのロードデシリアライズと初期設定
layoutSubviews()フレーム変更時子要素のジオメトリの再計算
draw(_:)初回表示時またはsetNeedsDisplay()後Core Graphicsを使用したコンテンツの描画
didMoveToSuperview()階層に追加された後最終設定、アニメーションの開始

すべてのメソッドはシステムによって自動的に呼び出され、開発者が手動で呼び出す必要はありません。例外はsetNeedsDisplay()で、システムにdraw(_:)の再呼び出しを通知します。

描画のためのdraw(_:)のオーバーライド

draw(_:)は、Custom UIViewでのカスタム描画のための主要メソッドです。このメソッド内で、開発者はCGContext(グラフィックコンテキスト)へのアクセスを取得し、Core Graphicsを使用して線、図形、テキスト、画像を描画できます。

システムは、ビューが画面に初めて表示されたときに自動的にdraw(_:)を呼び出します。後続の呼び出しは、ビューを再描画が必要としてマークするsetNeedsDisplay()によってトリガーされます。重要:draw(_:)を直接呼び出さないでください。キャッシュメカニズムが破壊され、パフォーマンスが低下します。

swift
override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else { return }

    // 背景塗りつぶし
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

    // 円を描く
    context.setStrokeColor(UIColor.white.cgColor)
    context.setLineWidth(4.0)
    let circleRect = rect.insetBy(dx: 20, dy: 20)
    context.strokeEllipse(in: circleRect)
}

この例では、draw(_:)は背景を青色で塗りつぶし、端から20ピクセルの余白で白い円を描画します。draw(_:)の各呼び出しはべき等でなければなりません。同じパラメータでの複数回の呼び出しは同じ結果を生成する必要があります。

効果的なdraw(_:)のルール

Appleはdraw(_:)内の作業を最小限にすることを推奨しています。UIBezierPathを事前に作成し、画像をキャッシュし、重い計算を実行しないでください。ビューが静的な場合は、絶え間ない再描画の代わりに、レンダリングされた画像を持つUIImageViewの使用を検討してください。

CALayer vs draw(_:): どちらを選ぶか

CALayerは、UIViewの視覚コンテンツを管理する基盤レイヤーです。多くのカスタム描画タスクは、draw(_:)をオーバーライドせずにCALayerのプロパティを設定することで解決でき、これは大幅に効率的です。

Apple Engineering(2024)によると、CALayerレベルの操作はGPUで実行され、draw(_:)はCPUベースのCore Graphicsレンダリングを通じて機能します。アニメーションやスムーズなトランジションには、CALayerとCABasicAnimationを使用することをお勧めします。

シナリオ推奨アプローチパフォーマンス
角丸layer.cornerRadiusGPU、高
影とグラデーションCAGradientLayer、shadowPathGPU、高
任意の図形UIBezierPathを使用したCAShapeLayerGPU、高
複雑なグラフィックCore Graphicsを使用したdraw(_:)CPU、中
カスタムフォーマットのテキストCATextLayerまたはdraw(_:)量に依存

アニメーション付きのベクター図形を描画するには、CAShapeLayerを使用してください。ハードウェアアクセラレーション対応で、draw(_:)を呼び出さずにpath、strokeStart、strokeEndのアニメーションをサポートします。

Custom UIViewのパフォーマンス最適化

Custom UIViewのパフォーマンスは、アニメーションの滑らかさと全体的なユーザーエクスペリエンスに直接影響します。主な問題は、draw(_:)の過剰な呼び出し、サブビューの最適でないレイアウト、キャッシュの欠如から発生します。

不要な再描画を避ける

setNeedsDisplay()の各呼び出しは、ビューの完全な再描画をトリガーします。変更がビューの一部のみに影響する場合は、特定の矩形を指定してsetNeedsDisplay(_:)を使用してください。CALayerのプロパティ(backgroundColor、cornerRadius、shadow)には再描画は不要です。GPUレベルで更新されます。

レンダリングされたコンテンツのキャッシュ

Custom UIViewのコンテンツがめったに変更されない場合は、UIGraphicsImageRendererで一度レンダリングし、UIImageとして保存します。次の再描画では、draw(at:)を使用してキャッシュされた画像を表示します。Core Graphicsでの再レンダリングよりも数十倍高速です。

swift
func renderToImage() -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: bounds.size)
    return renderer.image { ctx in
        drawHierarchy(in: bounds, afterScreenUpdates: true)
    }
}

静的レイヤーにはshouldRasterizeを使用する

CALayerのshouldRasterizeプロパティは、レイヤーのラスター表現のキャッシュを有効にします。透明度と影のある静的なビューでこれを有効にすると、コンポジットの負荷が軽減されます。アニメーションビューでは無効にしてください。変更のたびにキャッシュがリセットされ、ラスター化はパフォーマンスを低下させるだけです。

よくある質問

Custom UIViewでdraw(_:)をオーバーライドする必要はありますか?

いいえ。draw(_:)はCore Graphicsを使用したカスタム描画にのみ必要です。ビューが標準サブビュー(UILabel、UIImageView)で構成され、CALayerを使用している場合、draw(_:)をオーバーライドする必要はありません。これによりパフォーマンスが向上することもあります。

StoryboardにCustom UIViewを追加するには?

キャンバスに通常のUIViewを配置し、Identity InspectorのClassフィールドにクラスを指定します。クラスが@IBDesignableでマークされている場合、変更はStoryboardにリアルタイムで表示されます。

init(frame:)とinit(coder:)の違いは?

init(frame:)はプログラムによるビュー作成時に呼び出され、位置とサイズを持つCGRectを渡します。init(coder:)はStoryboardまたはXIBからのデシリアライズ時に呼び出されます。正しく動作させるには、両方を実装する必要があります。そうしないと、Interface Builderからロードするときにビューがクラッシュします。

draw(_:)が呼び出されないのはなぜですか?

最も一般的な理由は、ビューのフレームがゼロ(幅または高さがゼロ)であることです。システムはゼロ寸法のビューに対してdraw(_:)を呼び出しません。layoutSubviews()でフレームを確認し、ビューが正しい制約で階層に追加されていることを確認してください。

完全な再描画なしでCustom UIViewのコンテンツを更新するには?

GPUアニメーション(position、opacity、transform)をサポートするプロパティにはCALayerを使用します。draw(_:)の部分的な更新には、変更領域のCGRectを指定してsetNeedsDisplay(_:)を使用します。システムはビュー全体ではなく、指定された領域のみを再描画します。

まとめ

  • Custom UIView — 標準のUIKitコンポーネントが不十分な場合に使用される、カスタム描画用にメソッドをオーバーライドしたUIViewのサブクラス
  • draw(_:) — Core Graphicsを使用したカスタム描画のメソッド。システムによって自動的に呼び出されます。直接の呼び出しは禁止されています
  • CALayer — GPU加速グラフィックス(影、角丸、図形)に推奨されるアプローチ。draw(_:)の代替として高いパフォーマンスを提供
  • init(frame:)およびinit(coder:) — 必須イニシャライザ。コードとStoryboardからの正しい動作のために両方を実装する必要があります
  • setNeedsDisplay() — draw(_:)を再呼び出しするようにシステムに通知。部分的な再描画にはCGRectのオーバーロードを使用
  • @IBDesignable — Interface BuilderでCustom UIViewのライブプレビューを可能にする属性。ビジュアル開発を簡素化
  • 静的なグラフィックの場合、UIGraphicsImageRendererを使用して結果をキャッシュし、準備済みの画像を描画します。これによりCPU負荷が軽減されます

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください