あなたの質問と、高度にカフェインされたあなたの反応に基づいて、答えは正しいが、あなたが求めていることから少し勘違いするかもしれないと思う。私はあなたが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で非常にシンプルかつきれいに実現されます。例外が発生することを許可します。
おかげで、私は何をしようとしているのかは疑問だった。あなたのソリューションはおそらく最良のものですが、デリゲート、参照、およびアクションの再ルーティングの複雑さは、私はおそらく、それぞれのメインのviewcontrollerビューで同じものを繰り返すことを意味します。 – cannyboy
参照とアクションが内部的にReusableViewTemplateと一貫している限り、関連するviewDidLoadsに 'reusableView.delegate = self;'を追加して、あなたが発明したプロトコルを実装するだけで簡単です。 loadNibNamed:owner:options:の2番目の引数を指定するビットは、NSBundleに 'ファイルの所有者'リンクを接続する相手を指定する場所です。 – Tommy
あなたが愚かではないにせよ、私の顔を見ると、あなたはあなたの説明が私の理解を少し超えていることを知っているでしょう。とにかくそれを働かせようとします。 – cannyboy