2012-03-07 8 views
1

私はUIViewのサブクラスを作成し、それにnibファイルをロードしているとします。
私はこれを実行します。nibファイルで作成されたUIViewをサブクラス化してオーバーライドする

MySubView.m 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MySubView" owner:self options:nil]; 

     [self release]; 
     self = [[nib objectAtIndex:0] retain]; 
     self.tag = 1; 
     [self fire]; 
    } 
    return self; 
} 

- (void)fire { 
    NSLog(@"Fired MySubView"); 
} 

今、私はいくつかのバリエーションを作成したいが、私はnibファイルをコピーしたくないので、私はこのようMySubViewをサブクラス化しようとすると、背景色を変える:

RedMySubView.m 


- (id)initWithFrame:(CGRect)frame 
    { 
     self = [super initWithFrame:frame]; 
    if (self) { 
     self.backgroundColor = [UIColor redColor]; 
     [self fire]; 
    } 
    return self; 
} 

- (void)fire { 
    NSLog(@"Fired RedMySubView"); 
} 

ビューが作成され、背景色は変更されますが、火災アクションはサブクラスによってオーバーライドされません。 fireメソッドを呼び出すと、結果はコンソールにFired MySubViewとなります。
どうすれば解決できますか?
私はペン先のレイアウトを保ちたいが、それに新しいクラスを与える。

+0

これをチェックするquestion iNeal

答えて

0

私は、MySubview初期化子initWithFrameの[self release]を使用して、初期化子で作成するクラスを破棄していると言います。クラスはloadNibNameメソッドによってロードされるため、nibで定義されているのと同じクラスを持ちます。 したがって、サブクラスで初期化子を呼び出すことは無意味です。

MySubview(例えばinitWithNibFile)で独自のペン先のコンストラクタを実装するようにしてください:

など
- (id) initWithNibFile:(NSString *) nibName withFrame:(CGRect) frame 

、あなたが今、本当にあなたのnibファイルという見上げる場合RedMySubview

- (id) initWithNibFile:(NSString *) nibName withFrame:(CGRect) frame { 
self = [super initWithNibFile:mynib withFrame:MyCGRect]; 
if (self) 
.... 

でこのコンストラクタを呼び出しますクラスとしてRedMySubviewがある場合は、火は に上書き可能です。 MySubviewとRedMySubviewの両方に使用する場合は、xibを複製する必要があります。 それともそのサブクラスで作成するだけinitWithNibFile初期化子とUIViewsを実装する抽象クラス(スタブ)を作成します。あなたは、基本的になるために、あなたの「自己」のオブジェクトを上書きself = [[nib objectAtIndex:0] retain]呼び出すと

MyAbstractNibUIView initWithNibFile:withFrame: 
MyRedSubview : MyAbstractNibUIView  red.xib 
MyGreenSubview :MyAbstractNibUIView  green.xib 
MyBlueSubview : MyAbstractNibUIView  blue.xib 
0

MySubViewはnibファイル内の基本オブジェクトであるため、MySubViewを使用します。呼び出し元のクラスがRedMySubViewの場合は、MySubViewにオーバーライドされるため、これは望ましくありません。

代わりにあなたがこのにMySubViewでご- (id)initWithFrame:(CGRect)frameを変更したい:

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MySubview" owner:self options:nil]; 

     // The base of the nib file. Don't set self to this, instead copy all of its 
     // subviews, and "self" will always be the class you intend it to be. 
     UIView *baseView = [nib objectAtIndex:0]; 

     // Add all the subviews of the base file to your "MySubview". This 
     // will make it so that any subclass of MySubview will keep its properties. 
     for (UIView *v in [baseView subviews]) 
      [self addSubview:v]; 

     self.tag = 1; 
     [self fire]; 
    } 
    return self; 
} 

をその火は二回発動する以外、あなたがMySubViewの両方でそれを呼び出すために、すべてのものは、「MyRedSubView」の初期化子で動作するはずですがおよびRedMySubView。

関連する問題