Xamarin Designer for iOS のカスタム コントロール

iOS 用 Xamarin Designerでは、プロジェクトで作成されたカスタム コントロールや、Xamarin コンポーネント ストアなどの外部ソースから参照されるカスタム コントロールのレンダリングがサポートされています。

警告

iOS Designer は、Visual Studio 2019 バージョン 16.8 および Visual Studio 2019 for Mac バージョン 8.8 で非推奨とされ、Visual Studio 2019 バージョン 16.9 および Visual Studio for Mac バージョン 8.9 から削除されています。 iOS ユーザー インターフェイスを構築する推奨される方法は、Xcode を実行している Mac 上で直接行う方法です。 詳細については、「Xcode を使用したユーザーインターフェイスの設計」を参照してください。

iOS 用 Xamarin Designerは、アプリケーションのユーザー インターフェイスを視覚化するための強力なツールであり、ほとんどの iOS ビューとビュー コントローラーに WYSIWYG 編集サポートを提供します。 アプリには、iOS に組み込まれているコントロールを拡張するカスタム コントロールが含まれている場合もあります。 これらのカスタム コントロールがいくつかのガイドラインを念頭に置いて記述されている場合は、iOS Designerによってレンダリングされ、さらに豊富な編集エクスペリエンスが提供されます。 このドキュメントでは、これらのガイドラインについて説明します。

必要条件

次のすべての要件を満たすコントロールがデザイン画面にレンダリングされます。

  1. これは、UIView または UIViewController の直接的または間接的なサブクラスです。 その他 の NSObject サブクラスは、デザインサーフェイスにアイコンとして表示されます。
  2. これには、 に公開する RegisterAttribute があります Objective-C。
  3. これには、必要な IntPtr コンストラクターがあります
  4. IComponent インターフェイスを実装するか、DesignTimeVisibleAttribute を True に設定します。

上記の要件を満たすコードで定義されたコントロールは、含まれているプロジェクトがシミュレーター用にコンパイルされるときにデザイナーに表示されます。 既定では、すべてのカスタム コントロールがツールボックス[カスタム コンポーネント] セクションに表示されます。 ただし、 CategoryAttribute をカスタム コントロールのクラスに適用して、別のセクションを指定できます。

デザイナーは、サード パーティ Objective-C 製ライブラリの読み込みをサポートしていません。

カスタム プロパティ

次の条件が満たされた場合、カスタム コントロールによって宣言されたプロパティがプロパティ パネルに表示されます。

  1. プロパティには、パブリック getter と setter があります。
  2. プロパティには 、ExportAttributeBrowsableAttribute が True に設定されています。
  3. プロパティ型は、数値型、列挙型、string、bool、 SizeFUIColor、または UIImage です。 サポートされている型のこの一覧は、今後拡張される可能性があります。

プロパティは、 DisplayNameAttribute で装飾して、プロパティ パネルに表示されるラベルを指定することもできます。

初期化

サブクラスの UIViewController 場合は、デザイナーで作成したビューに依存するコードに対して ViewDidLoad メソッドを使用する必要があります。

その他NSObjectのサブクラスの場合UIView、カスタム コントロールがレイアウト ファイルから読み込まれた後で初期化を実行するには、AwakeFromNib メソッドを使用することをお勧めします。 これは、コントロールのコンストラクターの実行時にプロパティ パネルに設定されたカスタム プロパティは設定されませんが、呼び出される前に AwakeFromNib 設定されるためです。

[Register ("CustomView"), DesignTimeVisible (true)]
public class CustomView : UIView {

    public CustomView (IntPtr handle) : base (handle) { }

    public override void AwakeFromNib ()
    {
        // Initialize the view here.
    }
}

コントロールがコードから直接作成されるように設計されている場合は、次のように、共通の初期化コードを持つメソッドを作成できます。

[Register ("CustomView"), DesignTimeVisible (true)]
public class CustomView : UIView {

    public CustomView (IntPtr handle) : base (handle) { }

    public CustomView ()
    {
        // Called when created from code.
        Initialize ();
    }

    public override void AwakeFromNib ()
    {
        // Called when loaded from xib or storyboard.
        Initialize ();
    }

    void Initialize ()
    {
        // Common initialization code here.
    }
}

プロパティの初期化と AwakeFromNib

iOS Designer内で設定された値を上書きしないように、カスタム コンポーネントでデザイン可能なプロパティを初期化するタイミングと場所に注意する必要があります。 例として、次のコードを使用します。

[Register ("CustomView"), DesignTimeVisible (true)]
public class CustomView : UIView {

    [Export ("Counter"), Browsable (true)]
    public int Counter {get; set;}

    public CustomView (IntPtr handle) : base (handle) { }

    public CustomView ()
    {
        // Called when created from code.
        Initialize ();
    }

    public override void AwakeFromNib ()
    {
        // Called when loaded from xib or storyboard.
        Initialize ();
    }

    void Initialize ()
    {
        // Common initialization code here.
        Counter = 0;
    }
}

コンポーネントはCustomViewCounteriOS Designer内の開発者が設定できるプロパティを公開します。 ただし、デザイナー内で設定されている値に関係なく、プロパティの値は常に Counter ゼロ (0) になります。 理由は次のとおりです。

  • CustomControl インスタンスがストーリーボード ファイルから拡張されます。
  • iOS デザイナーで変更されたすべてのプロパティが設定されます (たとえば、 の Counter 値を 2 に設定するなど)。
  • AwakeFromNibメソッドが実行され、コンポーネントInitializeの メソッドが呼び出されます。
  • プロパティの値のCounter内部Initializeでは、0 (0) にリセットされます。

上記の状況を解決するには、(コンポーネントのコンストラクター内など) 別の場所で プロパティを初期化 Counter するか、 メソッドをオーバーライド AwakeFromNib せず、コンポーネントがそのコンストラクターによって現在処理されているものの外部でそれ以上の初期化を必要としない場合は を呼び出 Initialize します。

デザイン モード

設計面では、カスタム コントロールはいくつかの制限に従う必要があります。

  • アプリ バンドル リソースは、デザイン モードでは使用できません。 イメージは、 UIImage メソッド を介して読み込まれるときに使用できます。
  • Web 要求などの非同期操作は、デザイン モードでは実行しないでください。 デザイン サーフェイスでは、アニメーションやコントロールの UI に対するその他の非同期更新はサポートされていません。

カスタム コントロールは IComponent を実装し、DesignMode プロパティを使用して、デザインサーフェイス上にある場合にチェックできます。 この例では、ラベルにデザイン サーフェイスに "デザイン モード" と実行時に "Runtime" が表示されます。

[Register ("DesignerAwareLabel")]
public class DesignerAwareLabel : UILabel, IComponent {

    #region IComponent implementation

    public ISite Site { get; set; }
    public event EventHandler Disposed;

    #endregion

    public DesignerAwareLabel (IntPtr handle) : base (handle) { }

    public override void AwakeFromNib ()
    {
        if (Site != null && Site.DesignMode)
            Text = "Design Mode";
        else
            Text = "Runtime";
    }
}

メンバーにアクセスする前に、 プロパティnullSite常に チェックする必要があります。 が nullの場合Siteは、コントロールがデザイナーで実行されていないと仮定しても問題ありません。 デザイン モードでは、 Site は、コントロールのコンストラクターが実行された後、 の前に が呼び出された後に AwakeFromNib 設定されます。

デバッグ

上記の要件を満たすコントロールがツールボックスに表示され、サーフェスにレンダリングされます。 コントロールがレンダリングされない場合は、コントロール内のバグまたはその依存関係の 1 つをチェックします。

デザイン サーフェイスでは、多くの場合、他のコントロールのレンダリングを続けながら、個々のコントロールによってスローされる例外をキャッチできます。 障害のあるコントロールは赤いプレースホルダーに置き換えられ、感嘆符アイコンをクリックして例外トレースを表示できます。

赤いプレースホルダーとしての障害のあるコントロールと例外の詳細

コントロールでデバッグ シンボルを使用できる場合、トレースにはファイル名と行番号が含まれます。 スタック トレース内の行をダブルクリックすると、ソース コード内のその行にジャンプします。

デザイナーが障害のあるコントロールを分離できない場合は、デザイン画面の上部に警告メッセージが表示されます。

デザイン画面の上部にある警告メッセージ

完全なレンダリングは、障害のあるコントロールが固定されるか、デザイン 画面から削除されると再開されます。

まとめ

この記事では、iOS デザイナーでのカスタム コントロールの作成と適用について説明しました。 最初に、コントロールが設計画面にレンダリングされ、プロパティ パネルでカスタム プロパティを公開するために満たす必要がある要件について説明しました。 次に、コントロールの初期化と DesignMode プロパティの分離コードを確認しました。 最後に、例外がスローされたときに何が起こるか、およびこれを解決する方法について説明しました。