- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个使用 Apple 的 Safari 框架的 macOS 工具。在 macOS 10.13 中运行时,该工具会链接到并从中加载
/System/Library/PrivateFrameworks/Safari.framework
一切正常。但在 macOS 10.12.6 中运行时,某些行为会丢失。根据对 DTrace 的一些探测,我认为这是因为我的工具需要加载最新的 Staging 框架,如下所示:
/System/Library/StagedFrameworks/Safari/Safari.framework
这显然是 Safari 所做的,因为如果我使用 lldb 附加到 Safari 并运行image list
,则在 10.13 中该列表仅包含前一个路径,而在 10.12.6 中仅包含后者。
我尝试了以下方法:
NSBundle* stagedBundle = [NSBundle bundleWithPath:@"/System/Library/StagedFrameworks/Safari/Safari.framework"];
在 10.13 中返回 nil,因为此时没有这样的目录。但是,在 10.12.6 中,我得到了一个 stagedBundle,然后:
NSBundle* privateBundle = [NSBundle bundleForClass:[BookmarksController class]];
[privateBundle unload];
[stagedBundle load];
卸载和加载显然有效,因为如果我记录这两个包的 -description
,在运行该代码之前,私有(private)包是(已加载) 且 暂存 包是(尚未加载),但运行该代码后,这些状态会根据需要进行交换。
但是没有效果。 (1) 如果我再次调用 -bundleForClass:
,传递一个已知在两个框架中的类,它会为我提供 Private 包。 (2) 如果我调用 -respondsToSelector:
,传递已知仅存在于 Staging 框架中的选择器,我会得到“否”。
我尝试按照建议调用_CFBundleFlushBundleCaches()
here ,但这并没有帮助。
我还尝试更改目标的 FRAMEWORK_SEARCH_PATHS
,并在我的 Mac 上安装 Staging 框架并链接到它,但由于这篇文章已经太长了,我'我只能说这产生的热量多于光。
在这种情况下如何有选择地加载框架?
更新
我尝试了另一种方法。重新阅读苹果的Framework Programming Guide后,尽管看起来确实过时了,但我认为这个框架需要弱链接。这样做了:
-load
和 -unload
调用-weak_framework Safari
这对我来说很有意义,在 10.13 和 10.12.6 中构建并运行,但它显然仍在 10.12.6 中加载不需要的私有(private)框架。 NSLog 将其报告为 bundle 的路径,并且类不会响应仅位于 Staging 框架中的选择器。
还有其他想法吗?
最佳答案
首先,免责声明:我强烈建议您不要在交付给用户的任何应用程序中依赖加载私有(private)框架。它很脆弱并且没有支撑。
也就是说,如果您确实想这样做,我的建议是使用 Safari 本身在框架的两个副本之间进行选择的相同技术,即 dyld
的 DYLD_VERSIONED_FRAMEWORK_PATH
环境变量。
引用dyld
man page :
This is a colon separated list of directories that contain potential override frameworks. The dynamic linker searches these directories for frameworks. For each framework found dyld looks at its
LC_ID_DYLIB
and gets thecurrent_version
and install name. Dyld then looks for the framework at the install name path. Whichever has the largercurrent_version
value will be used in the process whenever a framework with that install name is required. This is similar toDYLD_FRAMEWORK_PATH
except instead of always overriding, it only overrides is the supplied framework is newer. Note: dyld does not check the framework's Info.plist to find its version. Dyld only checks the-current_version
number supplied when the framework was created.
简而言之,这会导致 dyld 在正在加载的框架和版本化框架路径中的框架之间执行版本检查,并加载更高版本。如果版本化框架路径不存在或者其中不存在相关框架,则将使用原始框架路径。
Safari 使用第二个 dyld
功能来简化其对 DYLD_VERSIONED_FRAMEWORK_PATH
(LC_DYLD_ENVIRONMENT
加载命令)的使用。此加载命令允许在链接时指定DYLD_*
环境变量,该变量将由dyld
在运行时尝试加载任何依赖库之前应用。如果没有这个技巧,您需要在启动应用程序之前将 DYLD_VERSIONED_FRAMEWORK_PATH 设置为环境变量,这通常需要繁琐的重新执行才能实现。
将这两个构建 block 放在一起,您最终会添加如下配置设置:
OTHER_LDFLAGS = -Wl,-dyld_env -Wl,DYLD_VERSIONED_FRAMEWORK_PATH=/System/Library/StagedFrameworks/Safari;
然后,您可以静态链接到 /S/L/PrivateFrameworks/Safari.framework
,或尝试在运行时动态加载它。两者都应该导致在运行时加载适当的框架。
为了解决您的问题所揭示的一些误解:
The unloading and loading apparently works, because if I log -description of those two bundles, before running that code the Private bundle is (loaded) and the Staged bundle is (not yet loaded), but after running that code those states are swapped, as desired.
不支持卸载包含 Objective-C 代码的共享库。我怀疑它所做的唯一事情是导致在NSBundle
实例上切换“已加载”标志,因为在dyld
的级别它被忽略。
In Build Settings > Framework Search Paths, listed paths to both frameworks' parent directories, with the Staged path before the Private path, because I want this one to load in macOS 10.12.6, where both exist.
框架搜索路径是一个仅在编译时使用的概念。在运行时,库的安装名称告诉dyld
在哪里可以找到要加载的二进制文件。
关于macOS:根据可用性在运行时加载一个或其他系统框架,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49375324/
我有这个代码: System.err.print("number of terms = "); System.out.println(allTerms.size()); System.err
我有以下问题:在操作系统是 Linux 的情况下和在操作系统是 MacOs 的情况下,我必须执行不同的操作。 所以我创建了以下 Ant 脚本目标: /u
我正在调用 system("bash ../tools/bashScript\"This is an argument!\"&"),然后我正在调用 close(socketFD) 直接在 system
使用最初生成的随机元素来约束随机数组的连续元素是否有效。 例如:我想生成一组 10 个 addr、size 对来模拟典型的内存分配例程并具有如下类: class abc; rand bit[5:0
我正在创建一个必须使用system(const char*)函数来完成一些“繁重工作”的应用程序,并且我需要能够为用户提供粗略的进度百分比。例如,如果操作系统正在为您移动文件,它会为您提供一个进度条,
我即将编写一些项目经理、开发人员和业务分析师会使用的标准/指南和模板。目标是更好地理解正在开发或已经开发的解决方案。 其中一部分是提供有关记录解决方案的标准/指南。例如。记录解决/满足业务案例/用户需
在开发使用压缩磁盘索引或磁盘文件的应用程序时,其中部分索引或文件被重复访问(为了论证,让我们说一些类似于 Zipfian 分布的东西),我想知道什么时候足够/更好地依赖操作系统级缓存(例如,Debia
我们编写了一个 powershell 脚本,用于处理来自内部系统的图像并将其发送到另一个系统。现在,业务的另一部分希望加入其中,对数据进行自己的处理,并将其推送到另一个系统。打听了一下,公司周围有几个
我正在尝试朗姆酒我的应用程序,但我收到以下错误:System.Web.HttpUnhandledException:引发了“System.Web.HttpUnhandledException”类型的异
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
所以我在其他程序中没有收到此错误,但我在这个程序中收到了它。 这个程序是一个我没有收到错误的示例。 #include int main() { system("pause"); } // en
我在 c# System.URI.FormatExption 中遇到问题 为了清楚起见,我使用的是 Segseuil 的 Matlab 方法,并且它返回一个图片路径 result。我想为其他用户保存此
我正在尝试像这样设置文本框的背景色: txtCompanyName.BackColor = Drawing.Color.WhiteSmoke; 它不喜欢它,因为它要我在前面添加系统,例如: txtCo
请帮助我解决 System.StackOverflowException我想用 .aspx 将记录写入数据库我使用 4 层架构来实现这一切都正常但是当我编译页面然后它显示要插入数据的字段时,当我将数据
我使用了一些通常由系统调用的API。 因此,我将 android:sharedUserId="android.uid.system" 添加到 manifest.xml, 并使用来自 GIT 的 And
我正在尝试创建一个小型应用程序,它需要对/system 文件夹进行读/写访问(它正在尝试删除一个文件,并创建一个新文件来代替它)。我可以使用 adb 毫无问题地重新挂载该文件夹,如果我这样做,我的应用
我想从没有 su 的系统 priv-app 将/system 重新挂载为 RW。如何以编程方式执行此操作?只会用 Runtime.getruntime().exec() 执行一个 shell 命令吗
我正在尝试制作一个带有登录系统的程序我对此很陌生,但我已经连续工作 8 个小时试图解决这个问题。这是我得到的错误代码 + ServerVersion 'con.ServerVersion' threw
当我“构建并运行”Code::Blocks 中的程序时,它运行得非常好!但是当我从“/bin”文件夹手动运行它时,当它试图用 system() 调用“temp.bat”时,它会重置。这是为什么?它没有
我想使用 system/pipe 命令来执行具有特殊字符的命令。下面是示例代码。通过系统/管道执行命令后,它通过改变特殊字符来改变命令。我很惊讶地看到系统命令正在更改作为命令传递的文本。 run(ch
我是一名优秀的程序员,十分优秀!