类别冲突

时间:2011-03-10 23:08:25

标签: objective-c categories

最近question让我想到了类别冲突,特别是涉及UIViewControllerRotation中的UIViewController.h类别。此类别包括shouldAutorotateToInterfaceOrientation:。如果有人想要覆盖这个方法(通过一个类别)并让它为每个UIViewController运行相同的代码(因为链接的帖子试图完成),那么他们有两个类别使用相同的方法 - 我阅读导致未定义的行为。

我尝试了一下,对于iOS 4.3中基于标准视图的应用程序,旋转逻辑回落到默认的纵向旋转,有效地忽略了类别。这是在我的shouldAutorotateToInterfaceOrientation:子类中没有定义UIViewController方法的。有趣的是,当我确定shouldAutorotateToInterfaceOrientation:方法并简单地调用return [super shouldAutorotateToInterfaceOrientation:]时,就会调用该类别。所以这给我留下了两个问题:

  1. 当你有类别方法冲突时,所有的赌注都是(行为方面的)吗?
  2. 如果他们想要覆盖继承继承的类别方法,那是不是运气不好?
  3. 非常感谢任何反馈!感谢。

3 个答案:

答案 0 :(得分:8)

建议; 不要那样做!!!

确实不希望在应用程序中的所有实例中覆盖任何给定UIKit类的所有实例的行为,原因有几个。

首先,您将以类可能无法处理的方式更改类的行为。同样,UI层次结构中无法控制的实例(通常是嵌入式复杂框架组件)的行为也会有所不同。

其次,您的实现无法知道原始实现的内部实现细节,以至于没有做出相同假设的风险。虽然你可以做一些类似混合的事情,但在这条道路上是非常脆弱的,并且将成为维护的噩梦。

答案 1 :(得分:2)

如果您有类别方法的冲突实现,那么未定义会发生什么。 UIViewController提供了shouldAutorotateToInterfaceOrientation:的默认实现,因此您无法通过类别附加自己的实现。

然而,您可能会劫持-[UIViewController shouldAutorotateToInterfaceOrientation:]并插入您自己的实现。我在Hijacking with method_exchangeImplementations()中对此进行了讨论。

必须非常小心地使用它,并且取决于UIViewController可能会发生变化的某些实现细节。所以我不建议这种方法解决大多数问题。通常,如果您想要一个“特殊的旋转视图控制器”,那就是子类化的用途。你创建了MYSpecialViewController和你的子类。使用劫持(或动态插入对象模型的任何其他机制)将影响系统中的每个视图控制器,包括Apple提供的可能或可能不会对其做出反应的视图控制器。但对于某些问题,这是一个非常有用的解决方案。

答案 2 :(得分:0)

我也同意bbum

但是,您可以安全地使用Class Cluster方法。通过这种方式,您将获得额外的好处:通过shouldAutorotateToInterfaceOrientation:访问原始super方法。

实施可能如下所示:

@interface UIViewController (MyViewController)
– (id) initMyControllerWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle;
@end

@implementation UIViewController (MyViewController)
– (id) initMyControllerWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
    [self release];
    return [[InheritedUIViewController alloc] initWithNibName:nibName bundle:nibBundle];
}
@end

通过简单继承覆盖shouldAutorotateToInterfaceOrientation:

@interface InheritedUIViewController: UIViewController 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
@end

@implementation InheritedUIViewController: UIViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// some implementation
return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation]; // optional
//return yourValue;
}
@end

现在,通过分类的UIViewController初始化initMyControllerWithNibName::,将调用InheritedUIViewController的{​​{1}}方法实现,并可以访问其原始实现。