1. ホーム
  2. ios

[解決済み] UIViewのサブクラス化のための適切なプラクティス?

2022-04-23 18:45:10

質問

UIViewベースのカスタム入力コントロールに取り組んでいるのですが、ビューを設定するための適切な練習方法を確認しようとしています。UIViewControllerで作業しているとき、それはかなり簡単です。 loadView と関連する viewWill , viewDid メソッドがありますが、UIViewをサブクラス化する場合、最も近いメッソドである `awakeFromNib , drawRect および layoutSubviews . (セットアップとティアダウンのコールバックという意味で考えています。) 私の場合、フレームと内部ビューのセットアップを layoutSubviews しかし、画面には何も表示されません。

ビューの高さと幅を正しく設定するには、どのような方法がありますか?(私の質問は、autolayoutを使用しているかどうかに関係なく当てはまりますが、2つの答えがあるかもしれません。) 適切な"ベストプラクティス"は何でしょうか?

どのように解決するのですか?

Appleは、サブクラス化する方法を明確に定義しています。 UIView というドキュメントがあります。

以下のリストを確認し、特に initWithFrame:layoutSubviews . 前者は UIView 一方、後者はフレームとそのサブビューのレイアウトを設定することを目的としています。

また、以下のことを忘れないでください。 initWithFrame: をインスタンス化する場合のみ呼び出されます。 UIView プログラムによって行われます。nibファイル(またはストーリーボード)から読み込んでいる場合。 initWithCoder: が使用されます。そして、その中に initWithCoder: はまだ計算されていないので、Interface Builderで設定したフレームを修正することはできません。提案の通り この回答では を呼び出すことを考えるかもしれません。 initWithFrame: から initWithCoder: を設定することで、フレームを設定することができます。

最後に UIView を nib (またはストーリーボード) から取得した場合、さらに awakeFromNib を使用すると、カスタムフレームやレイアウトの初期化を実行することができます。 awakeFromNib を呼び出すと、階層内のすべてのビューがアーカイブされずに初期化されたことが保証されます。

のドキュメントから NSNibAwaking (のドキュメントに取って代わられました。 awakeFromNib ):

他のオブジェクトへのメッセージは、awakeFromNib の中で安全に送信できます。このとき、すべてのオブジェクトがアーカイブされておらず、初期化されていることが保証されます (もちろん、必ずしも目覚めたわけではありませんが)。

また、autolayoutでは、ビューのフレームを明示的に設定してはいけないということも知っておくとよいでしょう。代わりに、十分な制約のセットを指定することになっており、フレームがレイアウトエンジンによって自動的に計算されるようにします。

そのまま ドキュメント :

オーバーライドするメソッド

初期設定

  • initWithFrame: このメソッドを実装することが推奨されます。また、このメソッドに加えて、独自の初期化メソッドを実装することもできます。 またはこのメソッドの代わりに

  • initWithCoder: Interface Builder の nib ファイルからビューをロードする場合、このメソッドを実装してください。 初期化

  • layerClass このメソッドは、ビューのバッキングストアに別のコアアニメーションレイヤーを使用する場合にのみ実装します。例えば OpenGL ES を使って描画する場合は、次のようにします。 このメソッドをオーバーライドして、CAEAGLLayerクラスを返します。

描画と印刷

  • drawRect: ビューがカスタムコンテンツを描画する場合、このメソッドを実装します。ビューがカスタム描画を行わない場合、このメソッドのオーバーライドは避けてください。 メソッドを使用します。

  • drawRect:forViewPrintFormatter: このメソッドは、印刷時にビューのコンテンツを別の方法で描画したい場合にのみ実装してください。

制約事項

  • requiresConstraintBasedLayout ビュークラスが正しく動作するために制約を必要とする場合、このクラスメソッドを実装してください。

  • updateConstraints ビューがサブビュー間のカスタム制約を作成する必要がある場合、このメソッドを実装します。

  • alignmentRectForFrame: , frameForAlignmentRect: これらのメソッドを実装することで、他のビューとの整列方法をオーバーライドすることができます。

レイアウト

  • sizeThatFits: このメソッドは、リサイズ中にビューに通常とは異なるデフォルトサイズを持たせたい場合に実装します。 の操作によって行われます。例えば、このメソッドを使って ビューが縮小してサブビューが表示されなくなるのを防ぐためです。 を正しく表示します。

  • layoutSubviews サブビューのレイアウトをより正確に制御する必要がある場合、このメソッドを実装します。 自動サイズ調整ビヘイビアが提供します。

  • didAddSubview: , willRemoveSubview: サブビューの追加と削除を追跡するために、必要に応じてこれらのメソッドを実装してください。

  • willMoveToSuperview: , didMoveToSuperview これらのメソッドを必要に応じて実装し、ビューの現在の動きを追跡します。 階層になります。

  • willMoveToWindow: , didMoveToWindow 必要に応じてこれらのメソッドを実装し、ビューの別ウィンドウへの移動を追跡します。

イベントハンドリング。

  • touchesBegan:withEvent: , touchesMoved:withEvent: , touchesEnded:withEvent: , touchesCancelled:withEvent: 実装 タッチイベントを直接処理する必要がある場合は、これらのメソッドを使用します。(タッチイベントの ジェスチャーベースの入力には、ジェスチャー認識ツールを使用します)。

  • gestureRecognizerShouldBegin: ビューが直接タッチイベントを処理する場合、このメソッドを実装してください。 ジェスチャーレコグナイザーが追加のアクションをトリガーするのを防ぎます。