Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c Can';t swizzle类方法_Objective C_Macos_Nsbundle - Fatal编程技术网

Objective c Can';t swizzle类方法

Objective c Can';t swizzle类方法,objective-c,macos,nsbundle,Objective C,Macos,Nsbundle,我正在为Mail.app制作一个插件。我想插件添加一个按钮到邮件的工具栏。为此,我决定最好的方法是调用函数在MessageViewer的initialize方法中添加此按钮(MessageViewer是Mail.app的FirstResponder类)。我正在修改的代码似乎工作得很好: + (void) initialize { [super initialize]; // class_setSuperclass([self class], NSClassFromString(@"MVM

我正在为Mail.app制作一个插件。我想插件添加一个按钮到邮件的工具栏。为此,我决定最好的方法是调用函数在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];  
以下是swizzling方法:

+ (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的initialize方法都会发生这种情况


这里有没有我没有考虑的问题

如果您想swizzle类方法,那么为什么要使用
class\u getInstanceMethod()
函数而不是
class\u getClassMethod()

而不是尝试手动实现swizzle,您应该使用。需要注意的是,JRSwizzle对
+jr\u swizzleClassMethod:withClassMethod:error:
的实现只是一个存根,但您可以简单地调用类的元类上的
+jr\u swizzleMethod:withMethod:error
(例如,只需传递
klass->>isa
而不是
klass
(其中
klass
是您正在使用的类).

您的代码格式不正确,看起来有点乱。您需要每个代码行至少有4个空格,以避免被损坏。谢谢,Kevin,JRSwizzle包看起来很棒!现在,我是否仍负责将我的类方法复制到我要swizzle的类中,或者有什么方法可以表明我的错误在jr_swizzleClassMethod调用中?(如果很明显,我很抱歉;我对ObjC非常陌生)
jr\u swizzleMethod:withMethod:error:
为您处理所有事情。它将您的方法复制到目标类中,并将IMP与您尝试重写的方法交换。好的,假设我在类Foo中有一个方法newMethod,我想在类栏中使用方法origMethod来swizzle它。我如何标记哪个类中的哪些方法我在切换?很抱歉,这有点误导。只有在重写超类中的方法时才会发生复制。通常在Swizzle方法时,您在原始类的类别中编写新方法。尝试在类之间复制方法没有任何意义,因为编译器将使用错误的c语言编译原始方法记住,你应该把你的
newMethod
写在类栏的一个类别上,然后把它刷一下。好吧,这更有意义。我知道把一个方法复制到另一个类是很奇怪的,但我正在为Mail.app写一个插件,所以我没有选择,因为它没有合适的插件架构。我会试试这个。再次感谢!