从子视图调用超级视图功能

时间:2012-12-09 23:41:37

标签: ios uiview uibutton uitextfield warnings

我有一个名为产品的UIView,它包含一个名为邮政编码的子UIView。

在邮政编码UIView中,我有一个简单的表单(一个UITextField和一个UIButton)。

当点击UIButton时,在邮政编码视图中运行一个方法(称为-storeData)...按预期工作。

现在在storeData里面我想在superview产品中调用一个方法。

这是我尝试过的,但我收到了警告:

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

//从此行ProductView *p = [self superview];

获取此警告
  

PostView.m:124:28:不兼容的指针类型初始化   'ProductView * __ strong',表达式为'UIView *'

3 个答案:

答案 0 :(得分:3)

尝试投射结果:

ProductView *p = (ProductView *)[self superview];

答案 1 :(得分:3)

根据我的评论,可能最好使用委托模式。

我知道除了检查父类的类类型之外,它还有很多代码,但它可以为ProductPostcode类分离提供更多功能。因此,实现handlePostChangeFor:方法的类不再必须是Product - 只要它实现SuperProtocol,它就可以是任何类。这反过来意味着您永远不必检查Postocde内的类类型,因为您不再关心它 - 您关心的是其他一些类可以完成您想要的工作。此外,如果superHandlerDelegate实例中的Postcode属性从未设置并保持nil,您仍然可以,因为Objective-c允许将消息发送到nil。< / p>

请注意,下面的代码是在非常广泛的笔触中完成的,我留下了很多无关紧要的东西。您的代码和此示例之间的一个主要区别是,您现在必须在handlePostChangeFor:方法中携带一个参数,以指示您正在处理更改的邮政编码。这是将两个类分离的直接结果。

// 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

答案 2 :(得分:2)

[self superview]的调用会返回UIView指针。您正在尝试执行以下操作:

UIView *view;
ProductView *p = view;

编译器无法知道在运行时view实际上是ProductView类型。这就是编译器抱怨的原因。

如上所述,解决方案是使用演员:

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

演员告诉编译器“嘿,别担心,我知道我在做什么。它确实是ProductView”。当然如果你错了,应用程序很可能会在运行时崩溃。

以下情况非常好:

ProductView *p;
UIView *view = p;

这是安全的,不会发出警告,也不需要演员表。这是有效的,因为已知ProductViewUIView的子类。