多个静态库,swizzling和dispatch_once

时间:2014-01-07 20:26:03

标签: iphone objective-c macos cocoa-touch cocoa

我有一个主要应用程序,我们称之为应用程序 它链接两个静态库 StatLib1 StatLib2
StatLib1 链接 StatLib2 库。

如您所见, StatLib2 库已链接两次。


StatLib2 库的一个类别中,我正在做一些调整:

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"test");

        [self itk_swizzleInstanceMethodWithSelector:@selector(someMethod:)
                                    withNewSelector:@selector(itk_someMethod:)];
    });
}

test被记录两次,这意味着这些方法将被重新调整为原始方法 我确定这是问题所在,因为当我删除 App 目标上的 StatLib2 链接时,这不会发生。


  1. 首先,为什么会这样?
  2. 如何在不实际删除应用目标 StatLib2 的链接的情况下解决此问题?

1 个答案:

答案 0 :(得分:3)

首先,静态库只是对象文件的存档,所以  你不能真正链接一个静态库与另一个静态库。 可能发生的是 StatLib2 的所有对象都被复制 StatLib1 即可。稍后,当应用程序链接时, StatLib2 的另一个副本 被添加到可执行文件中。

所以你以load方法的两个“实例”结束,每个实例都有自己的 static dispatch_once_t onceToken。这两个方法在类时调用 加载,每个都执行自己的dispatch_once()块。

的输出也显示了这一点
NSLog(@"test: class=%p, token=%p", self, &onceToken)

test: class=0x7fff7c76cdc8, token=0x100021f60
test: class=0x7fff7c76cdc8, token=0x100021f98

该类是相同的(因为它是同一类的类别),但是 onceToken不同。

作为解决方案,您应该只将最终的可执行文件链接到两者 静态库。