2013-03-08 2 views
8

I Нужно переопределить метод с использованием категории. Я также знаю об опасностях, связанных с этим (это частный класс внутри другого класса, и никто никогда не напишет еще один метод переопределения категории, поэтому не гарантируется неопределенное поведение). Я видел много подобного questions, но они все адреса подавление компилятора предупреждения использовать что-то вроде этого:Как вы подавляете предупреждение компоновщика при переопределении метода экземпляра класса в категории

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" 

// do your override 

#pragma clang diagnostic pop 

Однако это по-прежнему оставляет компоновщика предупреждения. Можно ли избавиться от него для моего конкретного переопределения, которое я считаю безопасным, в Xcode 4.6?

Описание проблемы sample GitHub project.

+0

Если вы воспользуетесь, зачем вам это нужно, мы могли бы предложить вам альтернативные решения. ваш примерный код не показывает нам причину, поскольку в этом примере это не очевидно, почему вы не используете подклассы. – vikingosegundo

+0

@vikingosegundo Я хочу заменить реализацию метода, сохраняя при этом доступ к его суперклассу (и нахожу это более элегантным подходом, чем метод swizzling). См. Этот вопрос для получения дополнительной информации: http://stackoverflow.com/questions/15291390/in-objective-c-how-do-you-entirely-replace-a-method-of-a-parent-class-while-pre В этом вопросе я попросил альтернативные решения проблемы. Здесь я просто спрашиваю, как подавить фактические предупреждения компоновщика для будущих ссылок. – lms

+0

Я бы никогда не подумал о том, чтобы подавить предупреждение элегантно. Может быть, это менее уродливо, чем метод swizzling ... – vikingosegundo

ответ

0

ОК, как я объяснил в своем комментарии, то, что вы пытаетесь сделать, опасно и не должно быть сделано. Я также предложил прочитать runtime documentation, чтобы понять, почему и узнать о других методах для достижения вашей цели. Вы должны это прочитать.

В любом случае, альтернатива тому, что вы делаете, который производит точные результаты без привлечения большого количества красных флагов, заключается в том, чтобы использовать среду выполнения для «пропустить» один класс в иерархии инициализации, эффективно «переопределяя» суперкласс.

Вот один вариант того, как это сделано, в вашем примере проекта, изменить реализацию класса FunkyBranch к этому:

#import "FunkyBranch.h" 
#import <objc/runtime.h> 

typedef id(*InitIMP)(id,SEL); 

@implementation FunkyBranch 

-(id) init 
{ 
    InitIMP superSuperInit = (InitIMP)class_getMethodImplementation([[self superclass] superclass], @selector(init)); 

    self = superSuperInit(self, @selector(init)); 
    if (self) 
    { 
     NSLog(@"FunkyBranch initialized"); 
    } 
    return self; 
} 

@end 

Он будет иметь те же результаты текущей реализации без опасности того, что вы делаете ,

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

+0

FWIW, это довольно разумный способ (OP) переопределить методы, например, для тестирования. Мы переопределяем методы таким образом, чтобы контролировать их реализации, используя категории, загруженные только для целевой цели тестирования. Это не так страшно, как все, ИМО. Это аккуратный трюк, хотя и немного запутанный. – tooluser

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