23

私は自分のUIViewサブクラスのXIBを作成するプロセスのほとんどに精通していますが、すべてが適切に機能しているわけではありません。ほとんどの場合、IBOutletsのリンクに関係しています。回り道のように見えるようにそれらを動作させることができます。

私のセットアップはこれです:

  • MyClass.hとMyClass.mがあります。UIView(ビューと呼ばれる)とUILabel(myLabelと呼ばれる)のIBOutletsがあります。オンラインのいくつかの例がこれが必要であることを示唆しているように見えたので、「view」プロパティを追加しました。実際には、ビュープロパティが見つからなかったためにクラッシュする問題が解決されました。これは、UIView親クラスでもないと思います。 。
  • MyClass.xibというXIBファイルがあり、そのファイルの所有者カスタムクラスはMyClassであり、そのクラスの.hと.mが存在した後に正しく事前入力されています。

私のinitメソッドは、問題が発生している場所です。

NSBundle mainBundleの「loadNibNamed」メソッドを使用して、所有者を「self」に設定しようとしました。これは、ビューのインスタンスを作成し、そのアウトレットがクラス内のアウトレットと自動的に一致することを期待しています(私は知っています)これを行う方法と私はそれに注意しています)。次に、「self」を、そのペン先のインデックス0のサブビューと等しくするのではなく、等しくしたいと思いました。

self = [super init];

またはそのようなもの。

私はここで間違ったことをしているように感じますが、オンラインの例ではinitメソッドでも同様のことが起こっていますが、それらはそのサブビュー0をviewプロパティに割り当て、子として追加します-しかし、それは合計ではありません2つのMyClassインスタンス?loadNibNamedを介してインスタンス化された子MyClassを含む、IBOutletsに本質的にリンクされていないもの?または、せいぜい、MyClassの直接の子として最初に必要だったすべてのIBOutletsを含む追加の中間UIViewを備えたMyClassインスタンスではありませんか?これは、instanceOfMyClass.frame.size.widthのようなことを行う場合、0を返すので、導入された子UIViewが探していた実際のフレームサイズを返すので、少し厄介です。

私が間違っているのは、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]; 

よろしくお願いします。

4

3 に答える 3

24

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?のサブクラスだと思います。その場合はUIView、.xibのが実際にMyClassクラスのものであることを確認する必要があります。これは、ビューを選択した後、InterfaceBuilderの右側の3番目のタブで定義されます

于 2012-11-23T19:13:35.497 に答える
7

を介してサブビューを作成しloadNibNamed、フレームを設定して、サブビューに追加するだけです。たとえば、NIBでインターフェイスが定義されてMyViewいるサブクラスであるクラスを使用して3つのサブビューを追加しています。UIViewMyView.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)。

于 2012-11-23T19:14:00.103 に答える
2

これが私が使用する1つの方法です:

  1. のサブクラスを作成しますUIView。これは呼び出されますMyClass
  2. ビューxibファイルを作成します。Interface Builderで開き、File's Ownerをクリックし、Identity Inspectorで、クラスを親ViewControllerのクラスに変更します ParentViewController
  3. オブジェクトのリストにすでにあるビューをクリックし、IdentityInspectorのクラスをに変更しMyClassます。
  4. 宣言したアウトレット/アクションは、MyClass(ファイルの所有者ではなく)ビューからクリックドラッグすることで接続されます。それらを変数に接続する場合はParentViewController、ファイルの所有者からクリックしてドラッグします。
  5. ここで、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];
}
于 2012-11-23T20:36:02.260 に答える