Several third-party libraries were added to the iOS app a few days ago, each with its own usefulness, because some libraries are not open source for some reason.
After adding, found that the app compilation does not pass, the error is as follows:
As can be seen from the error description, the app in the connection process, found some duplicate symbols, namely the same OC class and methods in different libraries have been implemented: Liblibpdrcore.a and LIBSIMPLECONFIGLIB.A The two libraries have conflict! Exactly, both of these libraries are used, and are not open source, as if suddenly walked into a dead end, because there is no way to modify the two libraries.
Search on the Internet, the person who encountered this problem is quite a lot, also proposed a solution: with the Lipo command to break down one of the classes, delete the duplicate symbols, and then re-packaged with the AR command to the library, I choose to modify the Liblibpdrcore.a this library:
1. View package information: Lipo-info liblibpdrcore.a, prompting FAT file, then representing this package is multi-platform support, such as ARMV7,ARMV64, etc.
2. Remove ARMv7 Bag: Lipo Liblibpdrcore.a-thin armv7-output armv7/liblibpdrcore_armv7.a
3. Extract the Object file (. o file): cd Armv7&ar XV liblibpdrcore_armv7.a
4. Delete Pdrserasyncsocket.o:rm PDRSERASYNCSOCKET.O based on error message
5. RePack: ar RCS liblibpdrcore_armv7.a *.O, remember to erase the old library
6. Repeat 1-5 change the arm64 or something.
7. Merge to Fat library: lipo-create liblibpdrcore_armv7.a liblibpdrcore_arm64.a-output Liblibpdrcore.a
Okay, now replace it with the new library, and compile it, and discover that the compilation was successful!
Wait! What does this have to do with the theme OC runtime? Just use some tools to remove the repeating symbol!
Yes, it does not matter, the following will formally enter the theme!
The compilation was successful, but actually running up? Sorry, crash, the error is as follows:
The reason may be: although the two libraries have a name-like OC class, some methods are the same, but not exactly the same, you can think that the two libraries rely on another open source library, but not the same version, as if to go into a dead end bird!
Careful analysis of some error message: Liblibpdrcore.a A place called the Asyncsocket class method AcceptOnAddress:port:error:, However, Asyncsocket in LIBSIMPLECONFIGLIB.A does not have this method, resulting in a call exception.
Now it's the OC runtime, and I'm just holding on to a try attitude. The previous time just look at this aspect, understand that OC can dynamically add, replace some classes of methods at runtime, solve some practical problems. Now I think of a way of thinking: Replace the Asyncsocket class with an empty function AcceptOnAddress:port:error: see if it works
1. Get the class type First: Class _asyncsocketclass = Nsclassfromstring (@ "Asyncsocket");
2. Add a method to the Asyncsocket class: Class_addmethod (_asyncsocketclass, nsselectorfromstring (@ "AcceptOnAddress:port:error:"), IMP , types); In this function, the following two parameters, one is the substitution method, one is the method parameter type, the substitution method parameter is good, directly defines a C format function, passes the function pointer to be able; How does the method parameter type get?
So, I thought of looking for some clues from the LIBSIMPLECONFIGLIB.A library, although it and liblibpdrcore.a use different versions of the Asyncsocket class, but some methods should be similar, get to help me complete the function Class_ The last parameter required by the Addmethod
3. Use Lipo and AR command to get the object file in LIBSIMPLECONFIGLIB.A: "ASYNCSOCKET.O"
4. View the export symbols for "ASYNCSOCKET.O": NM ASYNCSOCKET.O, sure enough, found a similar, method name is different, the name of the parameter is the same
5. Take a look at the export symbols of the PDRSERASYNCSOCKET.O in the Liblibpdrcore.a library, indeed there is "AcceptOnAddress:port:error:" This method, we know that the target file has been removed by us
6. Judging from the name, the two method parameters are the same, and the method Acceptoninterface does exist, with method_gettypeencoding to obtain the type of the method can get Class_addmethod the last parameter, with this idea , complete the following code:
void impfunc (Class cls, sel _cmd) { if ([Nsstringfromselector (_cmd) isequaltostring:@ "acceptonaddress"]) { //method of invoking the acceptoninterace of CLS }}- (BOOL) Application: ... { class _asyncsocketclass = nsclassfromstring (@ "AsyncSocket"); method _acceptoninterface = class_getinstancemethod (_asyncsocketclass, nsselectorfromstring (@ "AcceptOnInterface:port:error:")); class_addmethod (_asyncsocketclass, nsselectorfromstring (@ "AcceptOnAddress:port:error:"), (IMP) impfunc, method_gettypeencoding (_ Acceptoninterface));}
7. After compiling and running, did go to the Impfunc, the program does not crash, but the related function is not normal, I think it is really to call Acceptoninterface this method is OK
8. I think of parsing _cmd parameters, take out the parameter value, and then call objc_msgsend send a message, try a lot of methods, no success; in fact, I still take a detour, you should also see, class_addmethod the third parameter, Directly with the implementation of the Acceptoninterface is not the right! Method_getimplementation can help us do, so the code becomes as follows, compiled and run, success!
-(BOOL) Application: ... {Class _asyncsocketclass = nsclassfromstring (@ "Asyncsocket"); Method _acceptoninterface = Class_getinstancemethod (_asyncsocketclass, nsselectorfromstring (@ "AcceptOnInterface:po Rt:error: ")); Class_addmethod (_asyncsocketclass, nsselectorfromstring (@ "AcceptOnAddress:port:error:"), Method_ Getimplementation (_acceptoninterface), method_gettypeencoding (_acceptoninterface));}
9. No, it's adjourned.
Resolving third-party library conflicts using OC Runtime