0

I have the following

  • A 3rd party xcframework (ThirdPartyFramework)
  • A private pod (written in Swift) that wraps the above xcframework (AdditionalSDK)
  • The main SDK pod, also written in Swift (MainSDK)
  • A project (MyProject)

What I want to achieve is MainSDK to use functionality from AdditionalSDK, if AdditionalSDK is present. If not, MainSDK should continue to work without the AdditionalSDK's functionality.

After digging around I stumbled into this question, which led me to this guide. I've tried other guides as well, without any luck. I've also noticed that in the original question, each podspec defines a vendored framework (Firebase, Facebook and other major SDKs also do the same). In my case only the AdditionalSDK defines a vendored framework. The MainSDK defines its source files (along with headers, modulemap, etc).

The #if canImport(AdditionalSDK) didn't work for me, as the guide also states. I then tried to implement Obj-C interoperability classes. I.e. I added AdditionalSDKInterop.{h,m} as below

// AdditionalSDKInterop.h

#import <Foundation/Foundation.h>
#import <MainSDK/MainSDK-Swift.h> // <-- First problem here

@interface AdditionalSDKInterop : NSObject

@property (weak, nonatomic) id<MainSDKInteropDelegate> delegate;

+ (BOOL)isModuleAvailable;

@end
// AdditionalSDKInterop.m

#import "AdditionalSDKInterop.h"
@import AdditionalSDK; // <-- Second problem here

@implementation AdditionalSDKInterop

+ (BOOL)isModuleAvailable {
    if ([AdditionalSDK class]) {
        return YES;
    } else {
        return NO;
    }
}

@end

The MainSDKInteropDelegate is a protocol in the MainSDK, which defines the methods that can be called from the AdditionalSDK.

@objc public protocol MainSDKInteropDelegate: class {
    @objc func initializeSDK()
}

My first problem is that I get MainSDK/MainSDK-Swift.h file not found in the AdditionalSDKInterop.h, but strangely not always. Bear in mind that I clean my project and I delete the Derived data prior to each build. Still, sometimes I get this error, sometimes not. My second problem is that I get Module AdditionalSDK not found, if I don't add pod 'AdditionalSDK' in the project's podfile.

What am I missing, any thoughts?

e_pie
  • 91
  • 1
  • 5

1 Answers1

0

My suggestion is like this:

  1. Anything used from AdditionalSDK in your other classes should be used via protocols.
  2. Have 2 implementations for those protocols: one with AdditionalSDK, and one as no-op (does nothing). It can be even a default extension on your protocols.
  3. Have a factory class that takes classes you implemented in Step 2, based on some "Swift Compiler - Custom Flags".
  4. Create 2 build targets: one for case with AdditionalSDK, and one for case without AdditionalSDK. The first target will include AdditionalSDK Pod, and classes you created in step 2 that use it. And it will set the flag to value that matches "has AdditionalSDK". The other target will include no-op classes, and opposite of the flag. Th e factory class itself you created in step 3 won't include anything from AdditionalSDK, so it can be included in both targets.

Roughly something like this:

// Member of both targets. Your classes only use this protocol
protocol MyOptionalSDKProxy {
   func something()
   ...
}

// Member of both targets
extension MyOptionalSDKProxy {
   func something() { /* no-op*/ }
}

// Member of target with AdditionalSDK
import AdditionalSDK //<-- only here import Additional SDK
class MyProxyWithAdditionalSDK: MyOptionalSDKProxy {
   func something() { print("hello from AdditionalSDK") }
}

// Member of target with no AdditionalSDK
class MyNoOpProxy: MyOptionalSDKProxy {}

// Member of both targets
class MyProxyFactory {
    static var proxy: MyOptionalSDKProxy {
        #if USEADDITIONALSDK // <-- a flag defined for target with AdditionalSDK
           return MyProxyWithAdditionalSDK()
        #else
           return MyNoOpProxy()
        #endif
    }
}

// Usage
let myProxy = MyProxyFactory.proxy
proxy.something()
timbre timbre
  • 12,648
  • 10
  • 46
  • 77
  • Hey @Kiril S, firstly thanks for the effort. From my understanding this assumes that I have access to set flags on the project's targets, which is not the case. `MyProject` is a developer's project who wants to integrate my `MainSDK`, maybe the `AdditionalSDK` as well. Am I right or did I misunderstand your answer? – e_pie Aug 26 '21 at 07:09
  • what I was suggesting is that `MyProject` sets that flag. So basically I suggest that your "maybe wants to integrate with AdditionalSDK" is expressed as 2 targets, with a different compile-time flag on `MyProject` – timbre timbre Aug 26 '21 at 17:14