XCode 12: 'SessionDelegate' has different definitions in different modules - swift

Edit:
This problem occurs after XCode 12 Beta5. Xcode doesn't allow different modules to define same names (Probably for public classes & protocols). Alamofire and Kingfisher appears to define SessionDelegate at the same time. I'm still trying to find a solution..
I'm implementing iOS 14 Widgets in our application. I have started working with XCode 12 Beta 2 and everthing was compiling fine. When I have updated XCode to XCode 12 Beta 6, I faced with following error:
'SessionDelegate' has different definitions in different modules;
first difference is definition in module 'Kingfisher.Swift' found end
of class
I'm also attaching the screenshot of the file with error.
Is there any way to edit header files to have different names for SessionDelegate for Alamofire or Kingfisher? Is there any workaround to overcome this issue?
Here are things I have tried so far:
I have updated both Alamofire and Kingfisher to latest version
I have cleaned Podfile.lock and all pods as well as Derived Data
I tried to compile with Legacy Build System

You can try SWIFT_INSTALL_OBJC_HEADER = NO, it works for me

At this moment (Xcode 12.0 or Xcode 12.2b2), the only possible solution is to rename the Objective-C interface and avoid conflicts. This could be done by one of:
Rename conflicting class entirely, update all places where it's used (e.g. replace SessionDelegate by KingfisherSessionDelegate)
Add #objc(...) attribute to a Swift class, which will update the Obj-C interface in a generated ...-Swift.h file and avoid the names conflict.
// SessionDelegate.swift
#objc(KFSessionDelegate)
class SessionDelegate: NSObject { ... }
// Kingfisher-Swift.h
#interface KFSessionDelegate : NSObject
...
#end
This solution is already included in the Kingfisher 5.15.4 release and could be applied to any other libraries and your own frameworks.
Also, the thread on Apple forums: https://developer.apple.com/forums/thread/658012

The error is saying that you have multiple classes with the same name SessionDelegate in different modules. This error is related to Xcode 12.
For now, a quick solution is to install the module with CocoaPods (if you're using Carthage) and if needed, rename the SessionDelegate interface.

If you guys need a temporary solution, here is how for Cocoapods users:
Clone the Kingfisher library to the same folder level with your project. You can get it from Github
Open Kingfisher.xcworkspace in XCode and rename SessionDelegate.swift file under Sources/Netowking to KingFisherSessionDelegate and change the class name as well accordingly.
Rename the usages of SessionDelegate to KingfisherSessionDelegate which is only available in Sources/Networking/ImageDownloader.swift as of Kingfisher version 5.15.0
Add local path in your Podfile
pod 'Kingfisher', :path => '../Kingfisher'

I too had the same issue, sam's solution worked for me but with one change. There are 2 pods with the same definition so i changed the value of SWIFT_INSTALL_OBJC_HEADER to NO for both the pods. After doing it i was getting import error in one of the pod. So then i changed SWIFT_INSTALL_OBJC_HEADER to YES for that particular pod which was having the import error and kept the other pods SWIFT_INSTALL_OBJC_HEADER to NO. This worked for me.

for me worked when I update the 'SWIFT_INSTALL_OBJC_HEADER' key in podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if target.name == 'Alamofire'
target.build_configurations.each do |config|
config.build_settings['SWIFT_INSTALL_OBJC_HEADER'] = 'No'
end
end
end
end
end

Related

Swift Package Manager (SPM) and Cocoapod Dependency Conflict

Overview
I have two dependencies, one available as a Swift Package, and the other only available as a Cocoapod. The problem is that each has a dependency on a third package, which results in undefined behavior when multiple versions exist.
At a basic level, here is a graphic of my dependencies
APP imports:
B (SPM) imports:
C (SPM) imports:
D (SPM) <-
E (Pod) imports:
D (Pod) <-
I would like to remove the D (Pod) version and point to the D (SPM) version either via a Podfile script or build script.
More specific information:
I have a NetworkingService Swift Package that imports Firebase, and my main app imports the NetworkingService. My Podfile imports GoogleMLKit/PoseDetection. Firebase and PoseDetection share dependencies that result in undefined behavior (runtime crash) when a duplicate is present.
Note: This error should be reproducible by removing the intermediary NetworkingService package and importing Firebase to the main app as a Swift package.
Podfile
platform :ios, '15.0'
target 'MyApp' do
use_frameworks!
pod 'GoogleMLKit/PoseDetection', '2.5.0'
end
In Package.swift
.package(
name: "Firebase",
url: "https://github.com/firebase/firebase-ios-sdk.git",
.upToNextMajor(from: "8.10.0")
),
They duplicate a few dependencies, including GoogleUtilities and FBLPromises. Launching the app after pod install crashes with runtime exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FBLPromise HTTPBody]: unrecognized selector sent to instance 0x6000017685d0'
Searching that brought me to this GitHub issue where a contributor mentions:
The duplicate warnings are indicative of non-deterministic behavior. When there are multiple copies of a library, the right one may or may not be chosen.
I then attempted to refactor all Cocoapod dependencies with a modified version of this script I found linked on another StackOverflow post. The attempt was to make PoseDetection explicitly point to symbols from GoogleUtilitiesCopy and FBLPromisesCopy. But it seems that even the existence of these copies, despite pointing to the corresponding dependency, created undefined behavior.
Partial Workaround
If I run pod install followed by File > Packages > Update to latest package versions. The app will launch without an immediate runtime crash. However, I encounter other runtime crashes later within the app.***
Ideal Solution
I would like to remove the duplicate pod dependencies and point to the SPM versions either via the Podfile or a build phase script, but I'm not sure where to begin.
Firebase can be imported as a pod, but I do not want to do this because I have an existing SPM infrastructure that depends on Firebase. I'd prefer not to convert all of these packages into pods.
The main problem with SPM and Cocapods is that:
SPM is not aware of Cocapods and Cocapods not aware of SPM.
I had a similar situation where:
pod library depends on some Library networking
SPM library also depends on the same Library networking.
There are two solutions I think are worth trying.
1.) remove the pod and try to use the XCFramework version of it (should be available). that means you should manually add the library to your project and it should be selected as embed & sign and also as required.
2.) you can convert the pod library to SPM by using a simple binary target. Basically, you need to create a Package file that points to the XCFramework in its archived version (hence it should be a zip file). that way the SPM graph will handle it by itself.
I know it's not ideal, but these two approaches works for me.

XCFramework "Cannot load underlying module"

I've built an SDK as an XCFramework, which shares dependencies with the app that uses it. When I build, I'm getting:
...SDK.swiftmodule/arm64-apple-ios.swiftinterface:20:8: Cannot load underlying module for...
This occurs in the Compile Swift Sources action and the break is in the import MySharedDepedency statement in the swiftinterface file
As stated, the SDK in the project as an xcframework bundle. MySharedDependency is fulfilled with cocoapods. use_modular_headers is set in the Podfile, it's modulemap is included in the linker flags (by cocoapods).
Its DOES work if I use the use_frameworks! flag in the Podfile but only with dynamic linkage and for internal politics reasons, I need this to work with static linkage. If I add the :linkage => :static argument, I get the same error as with no use_frameworks! call
I've tried changing the order of the linked frameworks in Build Phases (so that the pods are linked before the SDK framework). I've tried adding recursive header/framework/module search paths everywhere I can find a MyDependency.modulemap...
Yes, I've cleaned caches, deintegrated, clean installed, erased deriveddata, restarted xcode, my machine, ...
Argh! Thanks for any help...
I had the same exactly the same scenario and the same problem
I solved using #_implementationOnly in every file from my xcframework's code like:
#_implementationOnly import Alamofire
After that just rebuild your XCFramework, clean and build your app's project.
It works like a charm without use_frameworks!

Using static libraries in Swift with CocoaPods fails for Realm

Since Xcode 9 it is possible to use static libraries by omitting the use_frameworks! flag in the Podfile. However, when used with the Pod RealmSwift this results in the following error:
[!] The following Swift pods cannot yet be integrated as static libraries:
The Swift pod `RealmSwift` depends upon `Realm`, which do not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set `use_modular_headers!` globally in your Podfile, or specify `:modular_headers => true` for particular dependencies.
Sadly, the proposed solution with use_modular_headers! does not work.
Other things I have tried include:
Using the latest Realm version (3.15.0)
Use the Objective C version and add Swift support, this won't build and give a module not found error in the RLMSupport.swift file .
Adding a bridging header for the Objective C version.
Endless clean, rebuild, Xcode relaunches and Derived Data folder cleaning.
It would not be preferable to circumvent CocoaPods and have this dependency be installed in a separate way, since that would make updating a more complex process. I hope there is a solution that works with CocoaPods, Realm and Swift.
I did the job doing following:
pod 'RealmSwift', '~> 3.17', :modular_headers => true
pod 'Realm', '~> 3.17', :modular_headers => true
As far as I can tell adding use_modular_headers! to top of Podfile works.
Adding s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } to .podspec doesn't work as far as I can tell. (Cocoapods 1.6.0-beta.2)
example:
target 'Opportunity' do
use_modular_headers!
end
I don't see why it wouldn't work. I got the same issue, and I added use_modular_headers! following way in the podfile and it worked.
target 'Pick Up Lines' do
use_modular_headers!
pod 'RealmSwift'
end
By the way, before doing any of it, make sure, you set the deployment target of the project as 11.0.

Why I cant import the library that in swift file after installing the the dependency in Cocoapods?

I already install this library, XLPagerTabStrip via Cocoapod. My pod file is look like this,and already hit pod install in terminal.
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'MyProject' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for MyProject
pod 'XLPagerTabStrip', '~> 8.0'
end
So everything is completed install,but when I want to import the library in Swift file,it giving an error ->> No such module 'XLPagerTabSript'.
I read a lot of question about this,which mention add the file path of the library to
Build Setting -> Search Paths -> User Header Search Paths. I also already did,but still giving the same error.
What I add in User Header Search Path is something like this:
${SRCROOT}/Users/Myname/Desktop/MyProject/Pods/XLPagerTabStrip
After adding the file path,I clean the project,build the project again,the tried to add in import XLPagerTabStrip to one of my swift file,the error still the same.
Can somebody let me know what is problem actually? Cause I beginner in Ios development,I totally no idea what I doing wrong.
I end up solve it by update my Xcode vesion and insert the file path of the library in inside
Build Setting -> Search Paths -> Framework Search Paths -> (Add the
file path of the library here)
By this I can import the library in swift file without any warning

Issue using static framework crashlytics

I have a A.framework which i am using in my swift app Test.
A.framework has a podspec which has s.dependency = 'Crashlytics'
Now when i do pod install on swift app Test, in Test's podfile i have to write below since i am using static framework:
pre_install do |installer|
# workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
def installer.verify_no_static_framework_transitive_dependencies; end
end
Now when i compile Test, it give me 'Crashlytics, file not found error'.
If i manually go to Test->Pods->A->Link binary with library->browse and add crashlytics.framework, error goes away.
How can i add a run script which will automate this manual step for me.
Thanks.