私は自分のUIViewサブクラスのXIBを作成するプロセスのほとんどに精通していますが、すべてが私にとって適切に機能しているわけではありません。ほとんどの場合、IBOutletsがリンクしているためです。私は彼らに回り道のように見えるように働かせることができます。
私のセットアップはこれです:
私のinitメソッドは私が問題を抱えているところです。
NSBundle mainBundleの 'loadNibNamed'メソッドを使用して所有者を 'self'に設定しようとしましたが、ビューのインスタンスを作成し、そのアウトレットがクラス内のアウトレットに自動的に一致することを期待していました(わかっています)これを行う方法と私はそれに注意しています)。次に、「自己」を、そのニブのインデックス0のサブビューに等しくしたいのではなく、
self = [super init];
またはそのような何か。
私はここで間違っていると感じていますが、オンラインの例ではinitメソッドで同様のことが行われていますが、サブビュー0をビュープロパティに割り当て、それを子として追加していますが、それは合計ではありません2つのMyClassインスタンス? loadNibNamedを介してインスタンス化された子MyClassを含む、本質的にIBOutletsにリンクされていないもの?あるいは、せいぜい、最初にMyClassの直接の子として必要なすべてのIBOutletを含む追加の中間UIViewを持つMyClassインスタンスではないのですか?導入された子UIViewが私が探していた実際のフレームサイズを返すとき、それは0を返すので、instanceOfMyClass.frame.size.widthのようなことをすることになると、それはわずかな不快感をもたらします。
私が間違っているのは、initメソッド内でloadNibNamedをいじっていることですか?私はもっとこのようなことをするべきですか?
MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];
またはこのように?
MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0];
ご協力をよろしくお願いいたします。
2番目のオプションは正しいものです。あなたができる最も防御的なコードは次のようなものです:
+ (id)loadNibNamed:(NSString *)nibName ofClass:(Class)objClass {
if (nibName && objClass) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:nibName
owner:nil
options:nil];
for (id currentObject in objects ){
if ([currentObject isKindOfClass:objClass])
return currentObject;
}
}
return nil;
}
そして、このように呼び出します:
MyClass *myClassInstance = [Utility loadNibNamed:@"the_nib_name"
ofClass:[MyClass class]];
// In my case, the code is in a Utility class, you should
// put it wherever it fits best
MyClassがUIView
のサブクラスであると想定していますか?その場合は、.xibのUIView
が実際にMyClassクラスのものであることを確認する必要があります。これは、ビューを選択した後、インターフェイスビルダーの右側の3番目のタブで定義されます
必要なのは、loadNibNamed
を介してサブビューを作成し、フレームを設定して、それをサブビューに追加することだけです。たとえば、私はMyView
クラスを使用して3つのサブビューを追加しています。これは、NIBで定義されているUIView
サブクラスであるMyView.xib
:
したがって、initWithFrame
サブクラスにUIView
を定義します。
- (id)initWithFrame:(CGRect)frame
{
NSLog(@"%s", __FUNCTION__);
self = [super initWithFrame:frame];
if (self)
{
NSArray *nibContents =
[[NSBundle mainBundle] loadNibNamed:@"MyView"
owner:self
options:nil];
[self addSubview:nibContents[0]];
}
return self;
}
したがって、たとえば、私のUIViewController
では、これらのサブクラス化されたUIView
オブジェクトをいくつかロードできます。
for (NSInteger i = 0; i < 3; i++)
{
CGRect frame = CGRectMake(0.0, i * 100.0 + 75.0, 320.0, 100.0);
MyView *myView = [[MyView alloc] initWithFrame:frame];
[self.view addSubview:myView];
// if you want, do something with it:
// Here I'm initializing a text field and label
myView.textField.text = [NSString stringWithFormat:@"MyView textfield #%d",
i + 1];
myView.label.text = [NSString stringWithFormat:@"MyView label #%d",
i + 1];
}
私は最初に使用コントローラーに助言しました、そして私は歴史的な参照のためにその答えを下に保ちます。
元の答え:
ここにはビューコントローラへの参照はありません。通常、UIViewController
のサブクラスがあり、それを使用してインスタンス化します
MyClassViewController *controller =
[[MyClassViewController alloc] initWithNibName:@"MyClass"
bundle:nil];
// then you can do stuff like
//
// [self presentViewController:controller animated:YES completion:nil];
NIBファイル、MyClass.xib
は、必要に応じて、ビューに関連するすべてのコードがあるUIView
の基本クラスを指定できます(たとえば、MyClassがUIView
のサブクラスであると想定しています)。
ここに私が使用する1つの方法があります:
UIView
のサブクラスを作成します。これはMyClass
と呼ばれますParentViewController
。MyClass
に変更します。MyClass
で宣言したアウトレット/アクションは、ビューからクリックしてドラッグすることで接続されます(ファイルの所有者ではありません)。それらをParentViewController
の変数に接続する場合は、ファイルの所有者からクリックアンドドラッグします。ParentViewController
でMyClass
のインスタンス変数を宣言する必要があります。ParentViewController.h
以下を追加します。
@class MyClass
@interface ParentViewController : UIViewController {
MyClass *myClass;
}
@property (strong, nonatomic) MyClass *myClass;
これを実装で合成し、viewDidLoad
メソッドに以下を追加します。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:self options:nil];
self.myClass.frame = CGRectMake(X,Y,W,H); //put your values in.
[self.view addSubview:self.myClass];
}