为什么屏幕保护程序会绕过方法调配?

Why would method swizzling be bypassed by the screen saver?

我正在为 Mac OS X 开发一个屏幕保护程序,我需要做一些方法调整,所以我做了一个小实验:

@implementation CAHTTPCookieStorage
+ (void) highjack {
    NSLog(@"Attempting to highjack cookies.");
    Class originalClass = [NSHTTPCookieStorage class];
    Method originalMeth = class_getClassMethod(originalClass, @selector(sharedHTTPCookieStorage));
    Method replacementMeth = class_getClassMethod([self class], @selector(patchedSharedHTTPCookieStorage));
    method_exchangeImplementations(originalMeth, replacementMeth);
}

+ (NSHTTPCookieStorage*) patchedSharedHTTPCookieStorage {
    NSLog(@"Cookies have been highjacked!!!!");
    return [CAHTTPCookieStorage patchedSharedHTTPCookieStorage];
}
@end

我从我的应用程序 AppDelegate.init() 和我的屏幕保护程序 ScreenSaverViewSubclass.init(...) 调用 CAHTTPCookieStorage.highjack()。虽然 运行 在预览模式下(在系统首选项中)设置我的应用程序或屏幕保护程序,但它工作正常,但是当我 运行 它作为适当的屏幕保护程序时,我可以看到消息 "Attempting to highjack cookies." 但是从不 "Cookies have been highjacked!!!!".

知道可能出了什么问题吗?也许线程有问题?方法是按线程调配的吗?

对此的进一步调查证明,这仅在双显示器模式下的 10.10 中是正确的,但在具有两个显示器的 10.9 或具有单个显示器的 10.10 中则不是。我不确定是什么原因造成的,但是使用 +load 方法进行调配解决了它:

+ (void) load {
    NSLog(@"Attempting to highjack cookies.");
    Class originalClass = [NSHTTPCookieStorage class];
    Method originalMeth = class_getClassMethod(originalClass, @selector(sharedHTTPCookieStorage));
    Method replacementMeth = class_getClassMethod([self class], @selector(patchedSharedHTTPCookieStorage));
    method_exchangeImplementations(originalMeth, replacementMeth);
}