IluTov
IluTov

Reputation: 6862

Multiple static libraries, swizzling and dispatch_once

I have a main application, let's call it App.
It links two static libraries, StatLib1 and StatLib2.
StatLib1 links the StatLib2 library.

As you see, the StatLib2 library is linked twice.


In a category of the StatLib2 library, I'm doing some swizzling:

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

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

test is logged twice, meaning the methods will be swizzled back to original.
I'm sure that this is the issue, since when I remove the link of StatLib2 on the App target, this does not happen.


  1. First of all, why does this happen?
  2. How can I fix this, without actually removing the link to StatLib2 on the App target?

Upvotes: 0

Views: 290

Answers (1)

Martin R
Martin R

Reputation: 539815

First of all, a static library is just an archive of object files, so you cannot really link one static library against another static library. What probably happens is that all objects of StatLib2 are copied into StatLib1. Later, when the application is linked, another copy of StatLib2 is added to the executable.

So you end with two "instances" of the load method, each with its own static dispatch_once_t onceToken. Both methods are called when the class is loaded, and each one executes its own dispatch_once() block. This is also shown by the output of

NSLog(@"test: class=%p, token=%p", self, &onceToken)

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

The class is the same (because it is a category for the same class), but the onceToken is different.

As a solution, you should only link the final executable against both static libraries.

Upvotes: 3

Related Questions