首先,免责声明:我强烈建议您不要依赖于在交付给用户的任何应用程序中加载私有框架。它很脆弱,没有支撑。
也就是说,如果您真的想这样做,我的建议是使用Safari本身用于在两个框架副本之间进行选择的相同技术,即
dyld
的
DYLD_VERSIONED_FRAMEWORK_PATH
环境变量。
引用
dyld
man page
:
这是一个以冒号分隔的目录列表,其中包含潜在的覆盖框架。动态链接器在这些目录中搜索框架。对于找到的每个框架,dyld查看其
LC_ID_DYLIB
并获得
current_version
和安装名称。Dyld然后在安装名称路径中查找框架。以较大者为准
当前\u版本
每当需要具有该安装名称的框架时,将在该过程中使用值。这类似于
DYLD_FRAMEWORK_PATH
除了不总是重写之外,它只重写所提供的框架较新。注意:dyld不检查框架的信息。plist查找其版本。Dyld仅检查
-current_version
创建框架时提供的编号。
简而言之,这会导致
dyld公司
在加载的框架和版本化框架路径中的框架之间执行版本检查,并加载更高版本。如果版本化的框架路径不存在或其中不存在有问题的框架,则将使用原始框架路径。
Safari利用第二个
dyld公司
简化其使用的功能
DYLD\u VERSIONED\u FRAMEWORK\u路径
这个
LC_DYLD_ENVIRONMENT
load命令。此load命令允许
DYLD_*
要在链接时指定的环境变量将由应用
dyld公司
在尝试加载任何依赖库之前的运行时。如果没有这个技巧,你需要
DYLD\u VERSIONED\u FRAMEWORK\u路径
作为启动应用程序之前的环境变量,这通常需要繁琐的重新执行才能实现。
将这两个构建块放在一起,最终会添加如下配置设置:
OTHER_LDFLAGS = -Wl,-dyld_env -Wl,DYLD_VERSIONED_FRAMEWORK_PATH=/System/Library/StagedFrameworks/Safari;
然后可以静态链接
/S/L/PrivateFrameworks/Safari.framework
,或尝试在运行时动态加载它。这两种方法都会导致在运行时加载适当的框架。
为了解决您的问题所揭示的一些误解:
卸载和加载显然是有效的,因为如果我记录这两个包的描述,在运行该代码之前,私有包(已加载)和暂存包(尚未加载),但在运行该代码之后,这些状态会根据需要进行交换。
不支持卸载包含Objective-C代码的共享库。我怀疑
只有
它所做的事情是在
NSBundle
实例,自
dyld公司
的级别将被忽略。
内置设置(>);框架搜索路径,列出了两个框架的父目录的路径,分段路径在私有路径之前,因为我想在macOS 10.12.6中加载这个路径,两者都存在。
框架搜索路径是一个仅在编译时使用的概念。在运行时,库的
安装名称
是什么告诉了我们
dyld公司
查找要加载的二进制文件的位置。