1. ホーム
  2. iphone

[解決済み] UIViewサブクラスのNibをロードする正しい方法

2023-01-22 17:59:52

質問

この質問は以前にもされたことがあると思いますが、回答が矛盾しており、混乱しているので、炎上させないでください。

私は再利用可能な UIView サブクラスを作成したい。nibファイルを使ってインターフェースを記述したい。

ここで、アクティビティ・インジケータを含むローディング・インジケータ・ビューとします。何らかのイベントでこのビューをインスタンス化し、ビューコントローラのビューにアニメートさせたいと思います。プログラム的に要素を作成し、initメソッド内でフレームを設定するなど、プログラム的にビューのインターフェースを問題なく記述することができました。

nib を使用してこれを行うにはどうしたらよいでしょうか。フレームを設定することなく、インターフェースビルダーで指定されたサイズを維持します。

こんな感じでなんとかやっていますが、きっと間違っているのでしょう(ピッカーを入れただけのビューです)。

 - (id)initWithDataSource:(NSDictionary *)dataSource {
        self = [super init];
        if (self){
            self = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@", [self class]] owner:self options:nil] objectAtIndex:0];
            self.pickerViewData = dataSource;
            [self configurePickerView];
        }
        return self;
    }

でも、selfを上書きしているので、インスタンス化するときに

FSASelectView *selectView = [[FSASelectView alloc] initWithDataSource:selectViewDictionary];
    selectView.delegate = self;

    selectView.frame = CGRectMake(0, self.view.bottom + 50, [FSASelectView width], [FSASelectView height]);

IBから拾ってもらうのではなく、手動でフレームを設定する必要がありますね。

EDIT: 私はこのカスタムビューをビューコントローラに作成し、ビューの要素を制御するためのアクセス権を持ちたいと思います。新しいビューコントローラーを作りたいわけではありません。

ありがとうございます。

EDIT: これがベストプラクティスかどうかは分かりませんが、私はこのようにしました。

FSASelectView *selectView = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@",[FSASelectView class]] owner:self options:nil] objectAtIndex:0];
    selectView.delegate = self;
    [selectView configurePickerViewWithData:ds];
    selectView.frame = CGRectMake(0, self.view.bottom + 50, selectView.width, selectView.height);
    selectView.alpha = 0.9;
    [self.view addSubview:selectView];
    [UIView animateWithDuration: 0.25 delay: 0 options:UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveEaseInOut animations:^{
                            selectView.frame = CGRectMake(0, self.view.bottom - selectView.height, selectView.width, selectView.height);
                            selectView.alpha = 1;
                        } completion:^(BOOL finished) {
                        }];

正しい練習がまだ必要

これは、ビューコントローラを使用して、nib名でinitするべきだったのでしょうか?コード内のいくつかの UIView 初期化メソッドで nib を設定するべきだったのでしょうか?それとも、私が行ったことは大丈夫ですか?

どのように解決するのですか?

MyViewClass *myViewObject = [[[NSBundle mainBundle] loadNibNamed:@"MyViewClassNib" owner:self options:nil] objectAtIndex:0]

再利用可能なカスタムビューを初期化するために使っています。


なお "firstObject"です。 を最後に使うと、少しすっきりします。 "firstObject" は、NSArrayとNSMutableArrayのための便利なメソッドです。

典型的な例として、テーブルのヘッダーとして使用するために xib を読み込む場合を示します。ファイルYourClass.mに

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return [[NSBundle mainBundle] loadNibNamed:@"TopArea" owner:self options:nil].firstObject;
}

通常であれば TopArea.xib で、ファイルの所有者をクリックし ファイルの所有者をYourClassに設定します . そして実際に をYourClass.hの中で を使えば、IBOutletのプロパティを持つことになります。で TopArea.xib で、それらのアウトレットにコントロールをドラッグすることができます。

で忘れてはいけないのは TopArea.xib を使用しなければならないかもしれません。 ビュー自体をクリックする をクリックし、それを何らかのアウトレットにドラッグして、必要であればそれをコントロールする必要があるかもしれません。(非常に有意義なヒントとして、テーブルのセル行に対してこれを行う場合、絶対にそうしなければなりません。)