2014-10-06 3 views
0

У меня есть метод:Невозможно вызвать метод категории селектора из основного класса

+ (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]; 
} 

проблема в том, что метод в категории никогда не вызывается, и я не могу найти проблему. Любая помощь?

+1

Никогда не используйте категорию для переопределения метода в Objective-C. Это неопределенное поведение и, вероятно, не будет работать так, как вы надеетесь. – rmaddy

ответ

2

Одна проблема здесь заключается в том, что вы не переопределяете метод. Селекторы будут одинаковыми (я считаю) - @selector (showModalFromController :), но метод не является. Для одного они имеют разные типы возвращаемых значений, другой - это метод класса (начинается с «+»), а один раз - метод экземпляра (начинается с «-»).

Вы должны убедиться, что ваш метод замены имеет подпись:

+ (id) showModalFromController: (UIViewController*) controller 

вместо

- (void) showModalFromController: (UIViewController*) controller 

Отсортировав это, вы один шаг ближе.

Как уже отмечал rmaddy, вы, вероятно, не хотите использовать категорию для переопределения метода.

Если вы пытаетесь заменить поведение, рассмотрите подкласс и используйте новый подкласс в тех местах, где это необходимо.

Если вы пытаетесь сделать что-то скрытно - заменив этот метод на протяжении всего вашего приложения, рассмотрите метод swizzling (рассмотрите эту опцию очень осторожно).

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 

Вы злоупотребляете имена селекторов путем определения двух селекторов с тем же именем в том же классе. Если вы хотите переопределить статический метод, вы должны использовать подкласс. Если вы хотите использовать другой метод в том же классе, используйте другое имя-селектор.

Смежные вопросы