6

私はタブバーコントローラーと同じタブの束を持っています。各タブの機能は異なりますが、UIはすべて同じです。ストーリーボードでは、1つのタブのフローとUIを設計し、基本クラスに設定しました。次に、タブを作成するときに、タブバーに追加する前にタイプキャストしてみましたが、機能しませんでした。

ストーリーボードでは、「TabView」と識別されたViewControllerにカスタムクラス「TabColor」があります

TabRed *red = (TabRed *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];
TabBlue *blue = (TabBlue *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];

ただし、TabRed / TabBlueではなく、TabColorのloadViewメソッドが呼び出されます。

また、nslogすると、結果はTabColorオブジェクトになります。

NSLog(@"%@", red)

期待:TabRed

実際:TabColor

4

2 に答える 2

6

tl; dr:

ストーリーボードとxibsには、シリアル化されたオブジェクトのコレクションが含まれています。ストーリーボードでクラスを指定すると、ストーリーボードをロードするときにそのクラスのインスタンスを取得できます。探している動作を取得する方法は、cocoa /cocoa-touchで一般的な委任パターンを使用することです。

ロングバージョン

ストーリーボード、および同様にxib / nibファイルは、実際には、エンコードされたオブジェクトのセットです。ストーリーボードで特定のビューがUICustomColorViewControllerであると指定すると、そのオブジェクトは、そのクラスのインスタンスのシリアル化されたコピーとして表されます。ストーリーボードがロードされinstantiateViewControllerWithIdentifier:て呼び出されると、ストーリーボードで指定されたクラスのインスタンスが作成され、返されます。この時点で、あなたはあなたが与えられたオブジェクトで立ち往生していますが、あなたは運が悪いわけではありません。

別のことをしたいと思っているように見えるので、委任を使用して機能が別のクラスによって処理されるようにViewControllerを設計できます。

2つのViewController間で異なる機能を指定するプロトコルを作成します。

@protocol ThingDoerProtocol <NSObject>
    -(void) doThing;
@end

ビューコントローラにデリゲートプロパティを追加します。

@interface TabColor
...
@property (strong, nonatomic) thingDoerDelegate;

次に、新しいオブジェクトにプロトコルを実装させ、必要なことを実行させます。

@implementation RedTabDoer
    -(void) doThing {
         NSLog(@"RedTab");
    }
@end

@implementation BlueTabDoer
    -(void) doThing {
         NSLog(@"BlueTab");
    }
@end

次に、ストーリーボードをロードするときに、これらのオブジェクトを作成して接続します。

TabColor *red = [storyboard instantiateViewControllerWithIdentifier:@"TabView"];
red.thingDoerDelegate = [[RedTabDoer new] autorelease];

TabColor *blue = [storyboard instantiateViewControllerWithIdentifier:@"TabView"];
blue.thingDoerDelegate = [[BlueTabDoer new] autorelease];

これにより、コントローラのデリゲートスロットに割り当てられているオブジェクトのタイプを変更することにより、ViewControllerの機能をカスタマイズできるようになります。

于 2012-08-30T14:56:29.203 に答える
3
TabRed *red = (TabRed *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];
TabBlue *blue = (TabBlue *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];

キャストは値を変更せず、コンパイラがそれらの値を解釈する方法を変更するだけです(そして、別の値の代わりにtypeを使用したときに文句を言わないようにします)。したがって、aTabColor*をaにキャストするTabRed*と、最初のポインターがインスタンスを指しているように見せかけるようにコンパイラーに指示されTabRedますが、ポインターが参照するオブジェクトはTabRedのインスタンスに変換されません。

waltflanaganが説明しているように、ストーリーボードと.xibファイルには実際のオブジェクトが含まれており、各オブジェクトのタイプはファイルの作成時に決定されます。実行時に変更することはできません。ただし、できることは、複数のViewControllerのそれぞれに同じビュー階層をロードさせることです。これを行うためにコードを書く必要さえありません。タブコントローラーと各タブのビューコントローラーを含む.xibファイルを作成するだけです。

IBタブコントローラー

タブごとに適切な種類のViewControllerが作成されるように、.xibで各ViewControllerのタイプを適切に設定してください。

IBカスタムクラスフィールド

各ビューコントローラの「NIB名」フィールドを設定して、これらのコントローラが使用するビュー階層を含む.xibファイルを指定します。各コントローラーに同じ.xibファイルを指定すると、各コントローラーはそれらのビューの独自のコピーをインスタンス化します。

IBNIB名の設定

ビューコントローラの共通のスーパークラスにIBOutletsを指定して、すべてのビューコントローラが同じアウトレットを持つようにします。そのスーパークラスを共通の.xibファイルの「ファイルの所有者」のタイプとして指定して、IBが使用可能なアウトレットを認識できるようにすることができます。ファイルの所有者は、実際には.xibをロードするオブジェクトのプロキシであるため、TabRedたとえば、ビューコントローラーの1つが共通のビュー.xibをロードすると、そのコントローラーが.xibのビューが接続されるコントローラーになります。.xibTabBlueをロードすると、そのオブジェクトはそれらのビューが接続されているオブジェクトになります。

これは最初は混乱しているように見えるかもしれませんが、それで遊んでください。これを理解すると、.xibファイル(したがってストーリーボード)を理解するのに役立ちます。初心者のときよりも魔法のようなものではありませんが、一度手に入れるとさらにクールに見えます。

于 2012-08-30T15:08:04.687 に答える