2011-07-12 7 views
0

私はいくつかのUIViewControllerを持っています。私はそれらのすべてで同じUIViewサブクラス(既存のUIViewControllerのビューの上に行く)を使用したいと思います。これはInterface Builderを使って可能ですか?複数のUIViewControllerサブクラスで同じUIViewサブクラスですか?

私は、UIViewを各UIViewControllerのビューにドラッグし、このドラッグされたUIViewのクラスをCustomViewに名前変更し、CustomView内のすべての要素が表示されるようにしたいと考えています...これは可能ですか?

答えて

2

あなたの質問と、高度にカフェインされたあなたの反応に基づいて、答えは正しいが、あなたが求めていることから少し勘違いするかもしれないと思う。私はあなたがInterface Builderでグラフィックを視覚的にデザインできるようにしたいと思う。あなたはカスタムUIViewサブクラスを書いておらず、ある種の方法でいくつかのUIViewを配置し、別のビューの子であるようにしています)、間接参照を介していくつかのビューコントローラに埋め込みます。同じユーザーインターフェイス要素をコピーして貼り付けているわけではなく、1か所で変更を行った場合、その変更はどこでも有効です。

私が知る限り、これを実現するためのInterface BuilderまたはXcode 4には組み込み機能はありません。 XIBは純粋なデータであり、UIViewにはアウトオブファイル参照を処理するスマートがありません。あなたのニブに入れ、その後

@implementation ReusableViewTemplate 

- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    // initialise ourselves normally 
    self = [super initWithCoder:aDecoder]; 

    if(self) 
    { 
     // load everything in the XIB we created 
     NSArray *objects = [[NSBundle mainBundle] 
          loadNibNamed:@"ReusableView" owner:self options:nil]; 

     // actually, we know there's only one thing in it, which is the 
     // view we want to appear within this one 
     [self addSubview:[objects objectAtIndex:0]]; 
    } 

    return self; 
} 

@end 

:あなたは何ができるか

はReusableView.xibが、その後のようになりますカスタムUIViewのサブクラスを書くと言うと呼ばれるあなたは1 XIBで使用するビューを、デザインであります再利用可能なビューを表示させたいUIViewで、 'class'を 'ReusableViewTemplate'またはそれを呼び出したものに設定します。

ReusableView XIBを開いて親ビューのタイプをReusableViewTemplateに設定すると、UIControls(ボタンやスイッチなど)を接続してそこに接続することができます。適切なデリゲートを設定するために、再利用可能なビューテンプレート用のカスタムプロトコルを定義し、再利用可能なビューを使用するすべてのビューコントローラでviewDidLoadをキャッチしたいと思うでしょう。

EDIT:これについてさらに考えてください。私はexample project(一般的なファイル共有サイトにあり、永久に生き残ることはできないかもしれません)というReusableViewクラスを作成しました。例えば、セグメントビューとボタンが含まれていて、次のようになります:

@implementation ReusableView 

/* 

    initWithCoder loads the relevant XIB and adds its 
    only object, which is a UIView, as a subview of this 
    one. If you don't like the double hierachy, you 
    could just have a list of views in the XIB and 
    addSubviews:, but then it'd much more difficult to 
    edit the thing graphically. You could strip the top 
    view programmatically, but this is just a simple 
    example, so... 

*/ 
- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    // initialise ourselves normally 
    self = [super initWithCoder:aDecoder]; 

    if(self) 
    { 
     // load everything in the XIB we created 
     NSArray *objects = [[NSBundle mainBundle] 
           loadNibNamed:@"ReusableView" 
           owner:self 
           options:nil]; 

     // actually, we know there's only one thing in it, which is the 
     // view we want to appear within this one 
     [self addSubview:[objects objectAtIndex:0]]; 
    } 

    return self; 
} 

@synthesize delegate; 
@synthesize segmentedControl; 
@synthesize button; 

/* 

    NSObject contains machinery to deal with the possibility 
    that a class may be sent a selector to which it doesn't 
    respond. 

    As of iOS 4, forwardingTargetForSelector: can be used to 
    nominate an alternative target for the selector quickly. 

    In previous versions of iOS, or in iOS 4 if you don't 
    respond to forwardingTargetForSelector:, you may take 
    delivery of the problematic invocation and deal with it 
    yourself. 

    Dealing with the invocation costs more than providing 
    a forwarding target for the selector, so its worth having 
    both. 

    If you're only targeting iOS 4 or above, you needn't 
    keep the implementation of forwardInvocation: below. 

    What we're doing is declaring a bunch of IBActions so 
    that we can wire changes up to them in Interface Builder. 
    By failing to implement them and providing the delegate 
    as the thing to talk to for any selectors we don't know, 
    we're allowing those wirings to be as though assigned 
    to the delegate. 

*/ 
- (id)forwardingTargetForSelector:(SEL)aSelector 
{ 
    return delegate; 
} 

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    [anInvocation setTarget:delegate]; 
    [anInvocation invoke]; 
} 

@end 
インタフェース付き

@interface ReusableView : UIView 
{ 

    IBOutlet id delegate; 

    IBOutlet UISegmentedControl *segmentedControl; 
    IBOutlet UIButton *button; 

} 

@property (nonatomic, assign) id delegate; 

@property (nonatomic, assign) UISegmentedControl *segmentedControl; 
@property (nonatomic, assign) UIButton *button; 

/* 

    NB: we're not actually going to implement these. We're 
    declaring them for the benefit of Interface Builder/Xcode 4. 

    What we'll actually do is, any time we receive a selector 
    we don't implement, hand it off to the delegate. So it's a 
    quick way of avoiding writing any glue code to pass messages 
    from this little reusable view to its delegate. 

    A better alternative could define a formal protocol that 
    forwards both the changed control and self from the 
    reusable view to its delegate. But that's obvious and 
    verbose, so has been omitted for the purposes of example. 

    The implementation as stands will generate compiler warnings, 
    but such is life. To get rid of the warnings, comment out 
    the two following lines, but only AFTER you've wired 
    everything up in Interface Builder/Xcode 4. They're left 
    uncommented here to help draw attention to the point about 
    selector/invocation forwarding that you'll see in the 
    @implementation. 

    !!!!!!!!!!!!!!! 

      HENCE: 

      delegates MUST implement the following methods. 

    !!!!!!!!!!!!!!! 

    We could work around that by checking at runtime whether 
    the actual delegate implements them and forwarding to 
    a dummy object that implements them to do nothing otherwise, 
    but that's slightly beyond the point of the example. 

*/ 
- (IBAction)reusableViewSegmentControlDidChange:(id)sender; 
- (IBAction)reusableViewButtonWasPressed:(id)sender; 

@end 

正味の効果は、ビューコントローラがXIB内型ReusableViewのUIViewのを持っている場合、それは実行時に挿入さReusableVew.xibの内容を取得することです。インタフェースビルダ/ Xcodeの4内ReusableViewの代表としてそのワイヤ自体を起動し、実装する場合:

- (IBAction)reusableViewSegmentControlDidChange:(id)sender; 
- (IBAction)reusableViewButtonWasPressed:(id)sender; 

そしてそれが埋め込まれたビューからメッセージを取得します。

これは、NSObjectの本来のセレクタ(iOS 4以降)または(以前のバージョンではよりコストの高い)呼び出しを実装することによって、Objective-Cで非常にシンプルかつきれいに実現されます。例外が発生することを許可します。

+0

おかげで、私は何をしようとしているのかは疑問だった。あなたのソリューションはおそらく最良のものですが、デリゲート、参照、およびアクションの再ルーティングの複雑さは、私はおそらく、それぞれのメインのviewcontrollerビューで同じものを繰り返すことを意味します。 – cannyboy

+1

参照とアクションが内部的にReusableViewTemplateと一貫している限り、関連するviewDidLoadsに 'reusableView.delegate = self;'を追加して、あなたが発明したプロトコルを実装するだけで簡単です。 loadNibNamed:owner:options:の2番目の引数を指定するビットは、NSBundleに 'ファイルの所有者'リンクを接続する相手を指定する場所です。 – Tommy

+0

あなたが愚かではないにせよ、私の顔を見ると、あなたはあなたの説明が私の理解を少し超えていることを知っているでしょう。とにかくそれを働かせようとします。 – cannyboy

2

はい、可能です。プロジェクト内に複数のUIViewControllerが複数ある場合は、UIImageViewをビューとして、自分のサブクラスであるUIViewでも同じことができます。

+0

同じUIViewサブクラスをいくつかのUIViewControllerビューに配置するにはどうすればよいですか? – cannyboy

+0

@cannyboy - あなたのペン先のIBで、IDインスペクタで既存のUIViewのクラス(または親ビューにドラッグしたもの)を変更します。 – highlycaffeinated

+0

私はUIViewペンを作成し、いくつかのボタンを表示しました。 CustomViewと呼ばれる添付ファイル.hと.mが作成されます。私はカスタムCustomViewの中のビューがCustomViewとして分類されていることを確認しました。そして、私のFirstViewControllerで、UIViewを既存のビューにドラッグしました。私はこのドラッグビューがCustomViewとして分類されていることを確認しました..しかし、ボタンは表示されません..私は間違っていると思いますか? – cannyboy

関連する問題