0

We have a static framework that we have built and it depends upon an SDK that we use to access ID's. This SDK has come out with a new version which has a new interface.

Currently the user would add our framework and the dependency SDK and everything would work fine. Now we want the user to be able to add our framework and either the old or new SDK and I'm not sure how to do this without creating multiple targets which we would rather not do. With the way I have it setup the user has to add our SDK and both the old and new SDK's.

I have a protocol SDKProtocol which is implemented by two classes NewSDKServices and OldSDKServices.

NewSDKServices won't compile unless the new SDK is present and OldSDKServices won't compile unless the old SDK is present. I figure this is OK since it is a precompiled framework and we can decided at runtime which to use.

Then I'd like to be able to do something like this, maybe with a ifdef to import and initialize the correct service.

if (useNewSDK) {
    _sdkService = [[NewSDKServices alloc] init];
} else {
    _sdkService = [[OldSDKServices alloc] init];
}

I've thought about weak linking these libraries but not exactly sure how it would work since you can't static link frameworks to other static frameworks. I'm hoping for some direction.

Both SDK's have a few headers and a .a.

user3440639
  • 169
  • 2
  • 11
  • Are you distributing your library as a binary or source code? – Mitchell Currie Jun 28 '18 at 00:47
  • @MitchellCurrie as a binary. – user3440639 Jun 28 '18 at 01:03
  • So you will weak link your framework to the other company SDK framework right? Just querying, is this an actual framework or a drag and dropped .a + .h files? – Mitchell Currie Jun 28 '18 at 02:00
  • @MitchellCurrie What the user does is add our `.a` and add the companies other SDK via .a + .h. They are not weak linking our framework, we are essentially an optional plugin that depends on the "larger" parent sdk. We are referencing them and we want to be able to reference either version of the SDK. – user3440639 Jun 28 '18 at 02:03

1 Answers1

1

I know you said you didn't want two targets. To be honest this is probably the best option as you are being explicit and up-front about the requirements so nobody can get confused easily. There are many ways to manage this by re-using source files and even having the way you suggested

if (useNewSDK) {
    _sdkService = [[NewSDKServices alloc] init];
} else {
    _sdkService = [[OldSDKServices alloc] init];
}

would be

#ifdef USE_SDK_NEW
    _sdkService = [[LinkedSDK alloc] init];
#else //USE_SDK_NEW
    _sdkService = [[LinkedSDK alloc] init];
#endif //USE_SDK_NEW 

However... if you really want to do it the other way and it works out, you must try to use weak linking.

If using weak linking it generally requires NSClassFromString(...) to access stuff. You would need to determine the availability of the SDK, hopefully someone has either added the info to the static classes like [NSClassFromString("TheSdk") performSelector: @"GetVersion"] or use the knowledge that other classes exist or do not exist. If the set of classes between two version is the same, you'd fallback to querying selectors or members.

Again this would not be pretty. You could make it less ugly by using the strategy pattern if you are familiar and have a strategy for the old SDK and the new SDK, and try to weak-link the classes without causing the compiler to require them.

If you are distributing yourself as a pod, you could create two targets and use the version to differentiate the required other SDK.

Mitchell Currie
  • 2,601
  • 3
  • 17
  • 25
  • Thanks for the answer! Could you elaborate on the `if you are familiar and have a strategy for the old SDK and the new SDK, and try to weak-link the classes without causing the compiler to require them.`? Our interaction with the SDK's is quite limited calling some getters. – user3440639 Jun 28 '18 at 02:21
  • I would use a file new newSDK.m and oldSDK.m to make the calls. That way each one can include a different version of the header. The .h file should have no reference to the SDK so that the entry point of your utility can reference it safely regardless of the version. Once you determine the version you either call `[OldSDK work]` or `[NewSDK work]` – Mitchell Currie Jun 28 '18 at 02:25
  • Hmm. I feel like that is kinda what I have. I have a protocol implemented for the old sdk and one for the new sdk. I also have a few files that I'd only want for the new SDK. Maybe multiple targets is the best route but I wish it wasn't. – user3440639 Jun 28 '18 at 02:58
  • Multiple targets can actually simplify things. You can add new targets and make the files shared. In some cases the target can be the same and you can just create separate schemes to inject different build variables. Since you are changing the linking it might be easier to use the targets and just share common logic.As a general rule if it is not vital to support both the old and new framework I would drop support for the old one. – Mitchell Currie Jun 28 '18 at 03:01
  • On the other hand also if the protocol is different between old and new SDK you can create an adapter to abstract the calls. The two targets can have all the same source files but adapter.h is shared and adapter.m is included differently based on the target such that the compiled in functionality varies for the required target (this is a kind of strategy pattern in itself) – Mitchell Currie Jun 28 '18 at 03:03