2010-12-08 54 views
4

我正在爲Mail.app製作一個插件。我希望這個插件爲Mail的工具欄添加一個按鈕。爲此,我決定最好的方法是調用函數在MessageViewer的initialize方法中添加此按鈕(MessageViewer是Mail.app的FirstResponder的類)。我修改的代碼似乎很好地工作:但是不能調整類方法

+ (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的初始化方法。

我在這裏沒有考慮到一些問題嗎?

+0

您的代碼格式不正確,看起來有點亂。您需要每條代碼行至少有4個空格才能使其不被破壞。 – 2010-12-08 02:10:00

回答

5

,而不是試圖實現手動混寫,你應該只使用JRSwizzle。請注意,JRSwizzle的實現+jr_swizzleClassMethod:withClassMethod:error:只是一個存根,但您可以簡單地在類的元類上調用+jr_swizzleMethod:withMethod:error(例如,只需傳遞klass->isa而不是klass(其中klass是您正在調整的類))。

+0

謝謝Kevin,JRSwizzle包看起來棒極了!現在,我仍然負責將我的類方法複製到要調試的類中,還是有方法可以在jr_swizzleClassMethod調用中指明此方法? (我很抱歉,如果它很明顯;我是ObjC的新手) – Aaron 2010-12-08 18:17:53

9

如果你想調整類方法,那麼爲什麼你使用class_getInstanceMethod()函數而不是class_getClassMethod()