AppDelegate类不适用于iOS Swift应用程序中的Obj-C嵌入式库

时间:2017-02-09 18:31:07

标签: ios objective-c swift appdelegate swizzling

我有一个用Objective C编写的库,作为Cocoapod发布。该库的部分功能是将AppDelegate类添加到任何应用程序中。当库被添加到一个简单的Objective-C应用程序(单页应用程序中没有任何内容)时,回调方法会被正确调整,每个人都很高兴。但是,当库被添加到类似的Swift应用程序时,由于AppDelegate为null(或nil),因此调配失败。

以下是图书馆内代码的一览:

(注意:此方法是从UIResponder的加载:方法调用的。)

UIResponder + MyCustomMethods.m

/**
 *  This class swizzles the methods needed to observe protocol methods
 */
@implementation UIResponder (WTAutomatics)

...

+ (void)swizzleAppDelegate:(SEL)original with:(SEL)replacement forProtocol:(Protocol *)protocol
{
    id appDel = [[UIApplication sharedApplication] delegate];
    Class appDelegate = [appDel class];
    // Alternatively, we can do this. Both work the same.
    // Class appDelegate = [[[UIApplication sharedApplication] delegate] class];

    NSLog(@"Starting swizzle: %@", NSStringFromSelector(original));    
    if (!appDelegate) {
        WTLog(@"Failed to swizzle because appDelegate is null.");
        return;
    }

    if (class_conformsToProtocol(appDelegate, protocol)) {
        // Do the method swizzling
        ...
    }
}

在上面的代码中,appDelegate的值是有效的,并且调制可以在任何Objective C应用程序中运行。但是, appDelegate在 Swift 应用程序中运行时为空,并且调配失败。

两种语言之间的应用程序委托的初始化顺序是否有所不同?还有其他我想念的东西吗?

2 个答案:

答案 0 :(得分:2)

在Obj-C应用案例中,我不确定这对你有用。在我的测试中,在应用程序的main()方法之前调用+ load,这是创建和初始化UIApplication的地方。在我的测试中,以下两行打印(null):

@interface UIResponder (blah)
@end
@implementation UIResponder (blah)
+ (void) load
{
    NSLog( @"application: %@", [UIApplication sharedApplication] );
    NSLog( @"delegate:    %@", [[UIApplication sharedApplication] delegate] );
}
@end

这是一个可以满足您需求的版本:

@interface UIResponder (blah)
@end
@implementation UIResponder (blah)
+ (void) load
{
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(didFinishLaunching:) name: UIApplicationDidFinishLaunchingNotification object: nil];

}
+ (void) didFinishLaunching: (NSNotification*) n
{
    NSLog( @"application: %@", [UIApplication sharedApplication] );
    NSLog( @"delegate:    %@", [[UIApplication sharedApplication] delegate] );
}
@end

此外,我不认为在类别扩展中实施+加载是明智的,因为您不知道这是否覆盖了类本身定义的某些+ load方法。我相信在这种情况下,未定义哪一个被称为?我得检查一下。一个更好的解决方案可能是创建自己的UIResponder派生类并将你的+ load垫片放在那里。

答案 1 :(得分:0)

Apple文档:+加载 每当将类或类别添加到Objective-C运行时时调用;实现此方法以在加载时执行特定于类的行为。

看起来您的AppDelegate尚未加载。试着从另一个地方打电话给你。 E.g。

+(void)initialize{
[self swizzle...];

}