无法通过主类中的选择器调用类别方法

时间:2014-10-06 17:00:01

标签: ios objective-c override objective-c-category

我有一个方法:

+ (id) showModalFromController: (UIViewController*) controller
{
    AxEmpAuthorizationController * autorizationController = [[self.class alloc] initWithNibName:NSStringFromClass(self.class) bundle:nil];
    [autorizationController performSelectorOnMainThread: @selector(showModalFromController:) withObject: controller waitUntilDone: YES];
    return [autorizationController authorelease];
}

我有一个类别AxEmpAuthorizationController+CustomLoginVC.h,我在其中覆盖了该方法:

- (void) showModalFromController: (UIViewController*) controller
{
    NavigationTopViewController* navigationController = [[NavigationTopViewController allocWithZone: NULL] initWithRootViewController: self];
    [controller presentModalViewController: navigationController animated: ![self.class isMain]];
    [navigationController release];
}

问题是类别中的方法从未被调用过,我无法找到问题。有什么帮助吗?

2 个答案:

答案 0 :(得分:2)

这里的一个问题是你不能覆盖这个方法。选择器将是相同的(我相信) - @selector(showModalFromController :),但方法不是。对于一个他们有不同的返回类型,另一个是一个类方法(以' +'开头),一个是实例方法(以' - '开头)。

您需要确保替换方法具有签名:

+ (id) showModalFromController: (UIViewController*) controller

而不是

- (void) showModalFromController: (UIViewController*) controller

一旦您对此进行了整理,您就会更近一步。

正如rmaddy在上面评论的那样,您可能不想使用类别来覆盖方法。

如果您正在尝试替换行为,请考虑在您需要的地方进行子类化和使用新的子类。

如果您尝试隐身做某事 - 在整个应用程序中替换此方法,请考虑方法调整(请仔细考虑此选项)。

答案 1 :(得分:0)

你误解了哪些类别;类别不是子类。您对"主要班级"的引用是不正确的。类别为您提供了分解源代码以提高可读性的能力,或扩展已经一成不变的类的类。

也就是说,如果您要从所有类别中获取所有来源并将其放在同一个@implementation块中(可能用#pragma mark -分隔以进行分组一致性),它应该阅读逻辑正确。您编写的代码转换自:

@implementation SomeClass
+ (id) showModalFromController: (UIViewController*) controller
{
  AxEmpAuthorizationController * autorizationController = [[self.class alloc] initWithNibName:NSStringFromClass(self.class) bundle:nil];
  [autorizationController performSelectorOnMainThread: @selector(showModalFromController:) withObject: controller waitUntilDone: YES];
  return [autorizationController authorelease];
}
@end

@implementation SomeClass (MyCategory)
- (void) showModalFromController: (UIViewController*) controller
{
  NavigationTopViewController* navigationController = [[NavigationTopViewController allocWithZone: NULL] initWithRootViewController: self];
  [controller presentModalViewController: navigationController animated: ![self.class isMain]];
  [navigationController release];
}
@end

进入这个:

@implementation SomeClass
+ (id) showModalFromController: (UIViewController*) controller
{
  AxEmpAuthorizationController * autorizationController = [[self.class alloc] initWithNibName:NSStringFromClass(self.class) bundle:nil];
  [autorizationController performSelectorOnMainThread: @selector(showModalFromController:) withObject: controller waitUntilDone: YES];
  return [autorizationController authorelease];
}

#pragma mark - MyCategory
- (void) showModalFromController: (UIViewController*) controller
{
  NavigationTopViewController* navigationController = [[NavigationTopViewController allocWithZone: NULL] initWithRootViewController: self];
  [controller presentModalViewController: navigationController animated: ![self.class isMain]];
  [navigationController release];
}
@end

您通过在同一个类中定义两个具有相同名称的选择器来滥用选择器名称。如果要覆盖静态方法,则应使用子类。如果您想在同一个类中使用不同的方法,请使用不同的选择器名称。