私はこれが非常に簡単であることを知っていますが、あまりにも多くの髪を引っ張った後、私は解決策にはほど遠い.
XIB などを使用してビューを作成する方法を説明するチュートリアルを見てきました。しかし、それらのどれも、私がここにいる状況に対処していません。
ラベルとボタンがほとんどないカスタム UIView サブクラスである XIB ファイルがあります。UIView サブクラスは再利用可能です。これが、単一の View コントローラー内にアウトレットを配置できない理由です。その結果、このビューの個々のコントロール (サブビュー) をカスタム UIView 自体に格納します。すべてのView Controllerに含まれるこのカスタムビューのサブビューをView Controllerが所有するべきではないため、これは論理的です。
問題は、UI 全体を完全に初期化する方法がわからないことです。
UIView サブクラスのコードは次のとおりです。
@interface MCPTGenericView : UIView
+(id)createInstance : (bool) bPortrait;
@property (weak, nonatomic) IBOutlet UIView *topView;
@property (weak, nonatomic) IBOutlet UIView *titleView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIButton *logoButton;
@property (weak, nonatomic) IBOutlet UITextField *searchTextField;
@property (weak, nonatomic) IBOutlet UIButton *menuButton;
@end
後で、この UIView の横向きにも同じ XIB ファイルを使用する予定であり、同じ XIB で横向きのコントロールを持つ同じ上記のアウトレットを使用する予定です。
そして、ここに実装があります:
@implementation MCPTGenericView
//@synthesize topView, titleLabel, titleView;
+(id)createInstance : (bool) bPortrait
{
UIView * topLevelView = nil;
MCPTGenericView * instance = [MCPTGenericView new];
NSArray * views = [[NSBundle mainBundle] loadNibNamed:@"MoceptGenericView" owner:instance options:nil];
int baseTag = (bPortrait)?PORTRAIT_VIEW_TAG_OFFSET:LANDSCAPE_VIEW_TAG_OFFSET;
// make sure customView is not nil or the wrong class!
for (UIView * view in views)
{
if (view.tag == baseTag)
{
topLevelView = view;
break;
}
}
instance.topView = (MCPTGenericView *)[topLevelView viewWithTag:baseTag + 1];
instance.searchTextField = (UITextField *)[topLevelView viewWithTag:baseTag + 2];
instance.menuButton = (UIButton *)[topLevelView viewWithTag:baseTag + 3];
instance.logoButton = (UIButton *)[topLevelView viewWithTag:baseTag + 4];
instance.titleView = [topLevelView viewWithTag:baseTag + 5];
instance.titleLabel = (UILabel *)[topLevelView viewWithTag:baseTag + 6];
return instance;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MCPTGenericView" owner:self options:nil] objectAtIndex:0]];
}
return self;
}
-(void)awakeFromNib
{
[super awakeFromNib];
[self addSubview: self.titleView];
[self addSubview:self.topView];
}
- (id) init
{
self = [super init];
if (self)
{
[[NSBundle mainBundle] loadNibNamed:@"MCPTGenericView" owner:self options:nil];
[self addSubview:self.topView];
[self addSubview:self.titleView];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code
[[NSBundle mainBundle] loadNibNamed:@"MCPTGenericView" owner:self options:nil];
[self addSubview:self.topView];
[self addSubview:self.titleView];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
うまくいったもの:
ビューコントローラーからの呼び出しに成功しましたinitWithFrame:frame
。そうすれば、すべてのコントロールが適切に初期化されていることがわかりました。しかし、すでに XIB を描画しているのに、なぜフレームを提供する必要があるのでしょうか? XIB の意図された用途であるため、loadNibNamed はフレーム設定とレイアウトを処理するべきではありませんか?
loadNibNamed が所有者オブジェクトを必要とする方法にも困惑しています。XIB から同じオブジェクトを取得するために、オブジェクトが既に必要なのはなぜですか? それも中途半端?
助けてください...