Не умеет метать методы класса - PullRequest
4 голосов
/ 08 декабря 2010

Я работаю над созданием плагина для Mail.app. Я бы хотел, чтобы плагин добавил кнопку на панель инструментов Mail. Для этого я решил, что лучшим подходом будет вызвать функцию добавления этой кнопки в метод инициализации MessageViewer (MessageViewer - это класс для FirstResponder Mail.app). Код, который я изменяю, кажется, работает хорошо:

+ (void) initialize
{  
[super initialize];

//  class_setSuperclass([self class], NSClassFromString(@"MVMailBundle"));
//  [ArchiveMailBundle registerBundle];


// Add a couple methods to the MessageViewer class.
Class MessageViewer = NSClassFromString(@"MessageViewer");

// swizzleSuccess should be NO if any of the following three calls fail
BOOL swizzleSuccess = YES;
swizzleSuccess &= [[self class] copyMethod:@selector(_specialValidateMenuItem:) 
                                 fromClass:[self class] 
                                   toClass:MessageViewer];
swizzleSuccess &= [[self class] copyMethod:@selector(unsubscribeSelectedMessages:) 
                                 fromClass:[self class] 
                                   toClass:MessageViewer];

Однако, когда я пытаюсь сделать то же самое, это не работает:

//  //Copy the method to the original MessageViewer
swizzleSuccess &= [[self class] copyMethod:@selector(_specialInitMessageViewer:)
                                 fromClass:[self class]
                                   toClass:MessageViewer];  

Вот методы извращения:

+ (BOOL)swizzleMethod:(SEL)origSel withMethod:(SEL)altSel inClass:(Class)cls
{
// For class (cls), swizzle the original selector with the new selector.
    //debug lines to try to figure out why swizzling is failing.
//  if (!cls  ||  !origSel) {
    //          NSLog(@"Something was null.  Uh oh.");
    //}
Method origMethod = class_getInstanceMethod(cls, origSel);

if (!origMethod) {
    NSLog(@"Swizzler -- original method %@ not found for class %@", NSStringFromSelector(origSel), 
          [cls className]);
    return NO;
}
    //if (!altSel) NSLog(@"altSel null.  :(");
Method altMethod = class_getInstanceMethod(cls, altSel);
if (!altMethod) {
    NSLog(@"Swizzler -- alternate method %@ not found for class %@", NSStringFromSelector(altSel), 
          [cls className]);
    return NO;
}

method_exchangeImplementations(origMethod, altMethod);

return YES;

}


+ (BOOL) copyMethod:(SEL)sel fromClass:(Class)fromCls toClass:(Class)toCls
{
    // copy a method from one class to another.
    Method method = class_getInstanceMethod(fromCls, sel);
    if (!method)
    {
        NSLog(@"copyMethod-- method %@ could not be found in class %@", NSStringFromSelector(sel),
              [fromCls className]);
        return NO;
    }
    class_addMethod(toCls, sel, 
                    class_getMethodImplementation(fromCls, sel), 
                    method_getTypeEncoding(method));
    return YES;
}

Кажется, что происходит сбой при вызове class_getInstanceMethod, потому что я получаю ошибку в журнале. Это происходит как для метода внутри моего собственного класса, так и для метода инициализации MessageViewer.

Есть какие-то ошибки, которые я здесь не принимаю во внимание?

Ответы [ 2 ]

9 голосов
/ 08 декабря 2010

Если вы хотите использовать методы класса, то почему вы используете class_getInstanceMethod() вместо class_getClassMethod()?

5 голосов
/ 08 декабря 2010

Вместо того, чтобы пытаться реализовать swizzling вручную, вы должны просто использовать JRSwizzle . Одно слово предостережения: реализация JRSwizzle +jr_swizzleClassMethod:withClassMethod:error: - просто заглушка, но вместо этого вы можете просто вызвать +jr_swizzleMethod:withMethod:error для метакласса класса (например, просто передать klass->isa вместо klass (где klass - это класс, который вы используете) кружишься)).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...