Class is implemented in both. One of the two will be used
Asked Answered
R

4

51

I have a project that has a dependency (installed via CocoaPods) using SocketRocket and have imported a static library from HeapAnalytics. Apparently the HeapAnalytics library already uses SocketRocket. I get no errors when compiling, but at runtime receive the following:

Class SRWebSocket is implemented in both [path] and [path].
One of the two will be used. Which one is undefined.

I'm not sure how to handle it because most solutions I've seen require compiling the static library yourself change class names and such, and I don't have access to the source.

Any recommendations?

Rochester answered 1/6, 2015 at 19:41 Comment(2)
I guess you'll have to stop linking against SocketRocket directly and instead rely on the one contained with HeapAnalytics.Boring
How do you stop linking against something that is installed as a dependency of something you setup via CocoaPods?Rochester
C
70

I wrote that error message!•

Either change the class name or don't link against said library.

How is your project configured? Is there anywhere where you explicitly link against SR? Or is it a product of linking against two static libraries that both already include SR?

If the former, then stop linking against SR directly and just inherit the version that came with the library already using it (warning: make sure it has the right version).

If the latter, then you are going to have to modify one of the libraries.

• Actually, I modified the error. It used to imply that one or the other would be used. But that wasn't really what was going on and the behavior was different across different platforms. Thus, it was changed so that it was far more precise in identifying that the behavior was undefined.

Copier answered 1/6, 2015 at 20:16 Comment(18)
Thanks bbum. Unfortunately, this confirms my suspicions that I'm going to have to completely modify one of the libraries.Rochester
Well the fix was a lot easier than I thought. I guess I thought I needed to do something really complicated but all I had to do was refactor -> rename all occurrences of SRWebSocket and it's accompanying inner classes. The only trouble I can foresee with doing this is that if the non-HeapAnalytics libraries are using a different version of SR, there could be some issues.Rochester
@Rochester Excellent! Yeah-- there really isn't a notion of namespaces in ObjC and, thus, collisions like this are problematic.Copier
How could namespaces help? It still would be SR:… and SR:…!?Forkey
@AminNegm-Awad Effectively, link time namespaces. That is, static library A would link the SR library and the symbols wouldn't be exposed beyond that library. B could do the same with a different copy. In practice, it causes as many problems as it solves.Copier
@Copier how can a project use framework classes which are in another framework that the project is linking? (like you say in your answer this apply to the first situation where project explicitly link against SR) if i dont put the import<framework_name> it wont recognize the framework classesDeprecative
is there a way to silence this warning?Phreno
@Copier is there something that can be passed to dyld, maybe via some DYLD env var to let it just pick one?Cantillate
@EdgarAroutiounian Nope; it is non-deterministic. The warning can't be silenced as it is, effectively, a ticking time bomb in a project. (Technically, it is deterministic, but it changes behavior across platforms and releases).Copier
@Copier thank you, any way to give a collection of dylibs and sanity check them before hand if duplicated symbols among collection, sans writing custom code.Cantillate
@Copier Thanks for your hard work, I have a question about this: will be a problem if importing two different external libraries that contains a class with the same name?Nickelson
@Nickelson yes. Same problem. One class will win.Copier
In a world where I configure my dependencies using CocoaPods, and my dependencies depend on I don't know what at whichever version they please, how do you propose to avoid this scenario? Imho, the tooling should take care of this -- either CocoaPods should detect duplicate dependencies and handle them correctly (in my case, it duplicates the exact same version of a framework), and/or the Swift build chain needs to disambiguate correctly.Beechnut
@Beechnut The only correct disambiguation is to not allow two classes of the same name to be in the link simultaneously. Without a hardline guarantee of instances of Class A never escaping the innards of a particular module, there is no way that a different class named A can co-exist in the runtime. Keep in mind that allow co-existance of different implementations of the same named class breaks a number of fundamental principals of Objective-C (and Swift).Copier
@Copier I agree that we can't have duplicates in the build artifact. I'm saying the tools should prevent that from ever happening.Beechnut
@Beechnut How? By definition, Objective-C allows the lookup of un-aliased class names. If you have a class named "BobsYourUncle", that name cannot be mangled and must be able to be universally looked up or you break a fundamental premise of Objective-C. So, the tools are preventing it by warning you that a problem exists.Copier
Speaking in complete ignorance of the details of Objective-C and the Swift compiler, if I use the/a standard dependency manager and build tool chain (CocoaPods, XCode, xcrun) and get such errors/warnings, something is broken. I don't know if it's the concept, the dependency manager, the compiler, the runtime, or a combination of them. And I don't care. Those are things that, in 2018, I expect tools to handle for me. If they don't, I'll use something else. Shifting the work onto the user is not a practicable solution here. </opinion>Beechnut
@Beechnut fix the ignorance and you’ll understand why it cannot be fixed without changing a fundamental design point of objc. What you are claiming is akin to claiming that “the fragile base class problem is ridiculous in 2018”. Every language or tool makes tradeoffs to solve a set of problems. Those tradeoffs include adopting other problems as a necessary part of the system. Objective-C embraces at runtime meta programming capabilities at the cost of no namespaces or other module divisions.Copier
I
5

In my case this error appeared when I unnecessarily added a source file to both my main app target and my test target:

Target Membership with both targets selected

Removing the test target from Target Membership solved it:

Target Membership with only one target selected

Ilona answered 2/3, 2018 at 10:41 Comment(0)
G
4

Overview:

The error suggests that the same symbol / class is defined twice.

Solution:

  • Check the frameworks linked to see if there are any duplicates. If so remove the duplicate
  • Clean build folder (Command + Shift + K)
  • If simulator, then reset the simulator and try
  • If device, restart the device and try

My experience:

I faced the same issue twice, once it was duplicate frameworks and the other time resetting simulator helped.

Granivorous answered 13/4, 2018 at 4:9 Comment(1)
In my case it was under Dependencies that I had the duplicate, which then fixed the issue for me.Cyr
A
2

I had this warning for more than a month, then I finally tried this and it worked for me:

  1. Reset the simulator (Menu: Hardware -> Erase all content and settings ... )
  2. Clean the project (Command + Shift + K)
  3. Clean the build folder (Command + Option + Shift + K)
  4. Run the code on the simulator again
Allie answered 19/7, 2018 at 13:19 Comment(1)
In my case, the above, less the reset. A simple cmd-K on the simulator was sufficient (as i had a few other dev apps that had setups I did not want to lose).Kwon

© 2022 - 2024 — McMap. All rights reserved.