1

Postcodeというサブ UIView を含むProductという UIView があります。

郵便番号UIViewには、単純なフォーム ( oneUITextFieldと one UIButton) があります。

UIButtonをクリックすると、( と呼ばれる) メソッドが-storeData郵便番号ビュー内で実行されます ... これは意図したとおりに機能します。

ここstoreDataで、スーパービュー Product のメソッドを呼び出したいと思います。

これは私がやろうとしたことですが、警告が表示されます:

if ([[self superview] class] == [ProductView class]) {
        ProductView *p = [self superview]; 
        [p handlePostChange]; 
    }

// この行からこの警告を取得しますProductView *p = [self superview];

PostView.m:124:28: 'UIView *' タイプの式で 'ProductView *__strong' を初期化する互換性のないポインター タイプ

4

3 に答える 3

3

結果をキャストしてみてください:

ProductView *p = (ProductView *)[self superview];
于 2012-12-09T23:47:42.867 に答える
3

私のコメントによると、委任パターンを使用する方が良いかもしれません。

Product単純に親のクラス タイプをチェックするよりもはるかに多くのコードであることはわかっていますが、クラスとクラスを切り離すことで、より多くの機能を得ることができますPostcode。したがって、handlePostChangeFor:メソッドを実装するクラスは、もは​​やそうである必要はありませんProduct。. SuperProtocolこれはつまり、 内のクラス タイプをチェックする必要がないことを意味します。これは、Postocdeもはや気にする必要がないためです。気にするのは、他のクラスが必要な作業を実行できるかどうかだけです。また、superHandlerDelegatea のインスタンスのプロパティがPostcode設定されずに残っnilている場合でも、Objective-c は にメッセージを送信できるため、問題ありませんnil

以下のコードは非常に大まかなブラシ ストロークで作成されており、多くの無関係なものを省略していることに注意してください。コードとこの例の主な違いの 1 つはhandlePostChangeFor:、変更を処理する郵便番号を示すために、メソッドでパラメーターを保持する必要があることです。これは、2 つのクラスを分離した直接的な結果です。

// Declare a protocol saying "Here is some functionality"
@protocol SuperProtocol
-(void) handlePostChangeFor:(Postcode*)postcode;
@end

// Product class says it will implement the functionality of the SuperProtocol
@interface Product : UIView <SuperProtocol>
@end

@implmementation Product
-(id)init
{
   if (!(self=[super init])) return self;
   ...
   // Create/locate the Postcode that is a child of this Product
   Postcode* postcode = ... // For example :- [[Postcode alloc] init];

   // Tell an instance of the Postcode class who will be supplying the SuperProtocol functionality
   postcode.superHandlerDelegate = self;
   ...
   return self;
}

// Implement the protocol's functionality
-(void) handlePostChangeFor:(Postcode*)postcode
{
  // Do Stuff with the data from the postcode instance
}
@end


@interface Postcode : UIView
// Identify who will implement the SuperProtocol functionality for this instance
@property (strong, nonatomic) id <SuperProtocol> superHandlerDelegate;
-(IBAction)storeData:(id)sender;
@end

@implementation Postcode
@synthesize superHandlerDelegate;
-(id)init
{
   if (!(self=[super init])) return self;
   ...
   // This is not required as NSObject's `alloc` sets everything to all zeroes
   // Note that you should not use "self.xxxxx" in an init method
   superHandlerDelegate = nil;
   ...
   return self;
}

-(IBAction)storeData:(id)sender
{
    ...
    // Tell the delegate to do the work
    [self.superHandlerDelegate handlePostChangeFor:self];
    ...
}

@end
于 2012-12-10T12:09:52.967 に答える
2

への呼び出しはポインタを[self superview]返します。UIViewあなたは次のことと同等のことをしようとしています:

UIView *view;
ProductView *p = view;

viewコンパイラは、実行時にが実際に型になることを知る方法がありませんProductView。これが、コンパイラが不平を言う理由です。

解決策は、前述のように、キャストを使用することです。

UIView *view;
ProductView *p = (ProductView *)view;

キャストはコンパイラーに「心配しないでください。私が何をしているのか知っています。それは本当にです」と伝えますProductView。もちろん、間違っていると、アプリは実行時にクラッシュする可能性が高くなります。

以下はまったく問題ありません。

ProductView *p;
UIView *view = p;

これは安全で、警告も出さず、キャストも必要ありません。ProductViewが のサブクラスであることがわかっているため、これが機能しUIViewます。

于 2012-12-10T00:02:21.247 に答える