【问题标题】:Calling super view function from sub view从子视图调用超级视图函数
【发布时间】:2012-12-09 23:41:36
【问题描述】:

我有一个名为 Product 的 UIView,其中包含一个名为 Postcode 的子 UIView。

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

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

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

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

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

// 从这一行得到这个警告ProductView *p = [self superview];

PostView.m:124:28:初始化不兼容的指针类型 带有“UIView *”类型表达式的“ProductView *__strong”

【问题讨论】:

  • 超类不知道子类。
  • 是的..但我在子类中进行此检查...
  • 是的,但这仍然不能让超类知道子类。你不是在编辑超类,是吗?
  • 我认为通过超级视图实现的协议使超级视图成为子视图的代表,您正在尝试做的事情会更好。
  • 顺便说一句,您通常使用isKindOfClassisMemberOfClass 检查班级成员资格。

标签: ios uiview uibutton uitextfield warnings


【解决方案1】:

尝试只投射结果:

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

【讨论】:

    【解决方案2】:

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

    我知道这比简单地检查父类的类类型要多得多,但它为您提供了更多功能,因为它将ProductPostcode 类解耦。因此,实现handlePostChangeFor: 方法的类不再必须是Product——它可以是任何类,只要它实现了SuperProtocol。这反过来意味着您永远不必检查 Postocde 中的类类型,因为您不再关心它 - 您所关心的只是其他类可以完成您想要的工作。此外,如果 Postcode 实例中的 superHandlerDelegate 属性从未设置并保持为 nil 您仍然可以,因为 Objective-c 允许将消息发送到 nil

    请注意,下面的代码是用非常广泛的笔触完成的,我遗漏了很多无关的东西。您的代码与此示例之间的一个主要区别是,您现在必须在 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
    

    【讨论】:

      【解决方案3】:

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

      UIView *view;
      ProductView *p = view;
      

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

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

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

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

      以下是完全没问题的:

      ProductView *p;
      UIView *view = p;
      

      这是安全的,不会发出警告,也不需要强制转换。这是可行的,因为已知ProductViewUIView 的子类。

      【讨论】:

      • 是的,很酷,谢谢...为了避免它在运行时崩溃,我仔细检查了超类是否属于 ProductView 类型。 IE。 if ([[self superview] class] == [ProductView class]) {
      • 是的,这很好。我是在做一个一般性的陈述。由于您进行了适当的运行时检查,因此您是安全的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多