Please correct me if my reasoning is wrong (I assume it's correct ):
As I build an iOS app, it's output is a package MyApp.app, and among the other things it contains a Mach-O binary MyApp: MyApp.app/MyApp.
We can detect which iOS public frameworks (e.g. UIKit, CoreData etc) MyApp uses by either running otool -L MyApp.app/MyApp, or searching for the particular symbols with some disassemlber tool e.g. Hopper.
Now, if we meet some DYLD error for a private framework during an app's launch, e.g.
dyld[93664]: Symbol not found: _OBJC_CLASS_$_SomeClass
Referenced from: /Applications/XcodeRC.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/FamilyCircleUI.framework/FamilyCircleUI
this means that FamilyCircleUI, which is a private framework, is referenced by some other public iOS framework. And we can't detect it with otool -L MyApp.app/MyApp, because public framework are not built into MyApp, just referenced from it!
So, the question is: in order to detect who's referencing FamilyCircleUI, do I need to run otool -L PublicIosFramework.framework/PublicIosFramework for each of the public frameworks used in the app, or is there much shorter way?
E.g.
- some documentation (Apple doesn't want to provide it, so maybe there're some reversed dumps I didn't found with Google)?
- some wild combination of
otool+grep+find+ls?
I would start with something fairly simple - set environmental variable
DYLD_PRINT_LIBRARIESto1in your target scheme.That in Xcode console on your app startup should yield something like:
However if that's not enough or maybe you'd like to automate something in the long run here are actual scripts (intended to be run as Xcode script phase) to traverse the main app executable binary and its frameworks, then recursively their referenced frameworks etc.
Script looking up
ASIdentifierManagersymbol:The script deliberately fails if at least one symbol occurance is found (you can change the logic by exiting with
0).Here's a script if you're looking for particular framework (in my example
AppTrackingTransparencyframework) using the same strategy:Both scripts are intended to be run as last Xcode build phases (so after the app has been built).
My original use case is for self inspecting for stuff rejected on Apple review.
A somewhat related operation but around verifying referenced frameworks vs actually embedded ones is covered in my answer here: https://stackoverflow.com/a/69560246/5329717