你能否在iOS上构建动态库并在运行时加载它们?

122
动态库在iOS(iPhone/iPad)上受支持吗?
在Xcode中,我尝试创建一个“新项目” - >“Framework & Library” - >“Cocoa Library (dynamic)” 。在项目设置中,我将“Base SDK”设为“iOS device 4.1”,目标设为“iOS4.1”,但出现了构建错误:
“target specifies product type 'com.apple.product-type.library.dynamic', but there's no such product type for the 'iphonesimulator' platform”。
我选择的构建是“Simulator -> Debug -> i386”。

不可以,但是您可以构建和链接一个静态库。 - bobobobo
4
iOS8+ 支持基于共享库的框架。 - eonil
1
@Eonil,你能详细解释一下吗?我想了解更多信息,如果有文章或链接的话,将不胜感激。 - Maxim Chetrusca
http://ddeville.me/2014/04/dynamic-linking - P i
3个回答

169
我并不是真的不同意DarkDust的答案,但如果我可以发挥一下我内心的比尔·克林顿,这取决于“支持”这个词的意思是什么 :)
苹果不希望你对App Store应用程序这样做,但操作系统肯定允许这样做。越狱应用程序一直在使用这种技术。你基本上使用标准的UNIX技术动态打开一个框架/库,然后在其中使用东西。dlopen函数允许你通过传递该框架或dylib的路径来打开库。从一些构建越狱应用程序的文档中,以下是调用自己单独的dylib中实现的init()函数的示例:
#include <dlfcn.h>

initWrapper() {
    char *dylibPath = "/Applications/myapp.app/mydylib2.dylib";
    
    void *libHandle = dlopen(dylibPath, RTLD_NOW);
    if (libHandle != NULL) {
        // This assumes your dylib’s init function is called init, 
        //    if not change the name in "".
        void (*init)() = dlsym(libHandle, "init");
        if (init != NULL)  {
            init();
        }
        dlclose(libHandle);
    }
}

此外,Xcode默认限制您无法为iOS构建动态库项目,但您可以通过编辑一些XCode xml文件来覆盖此限制:
在iOS上构建和使用dylib 一旦这样做,您就可以构建普通的iOS.dylib库,并按照上面的示例代码使用它。(是的,每当您安装新的XCode版本时,您可能需要再次解锁此功能。)
因此,这不是技术上的限制,而是App Store政策的限制。如果您不受App Store限制,则可以这样做。请注意,此技术需要越狱,尽管如果应用程序被沙箱化,可能会限制dylibs可以从哪里加载。
编辑:为了确保这些信息不会因为链接失效而丢失,这里提供我之前分享的如何在Xcode中启用iOS dylibs的链接内容。(注意:这个过程仍然适用于Xcode 4,但请参考下面的评论更新路径等信息。)来源是iOS Place blog
Xcode不允许您为iOS构建dylib。如果应用程序不是单一二进制文件,则将被拒绝。但我有一个具有插件架构以加载可选模块的应用程序。我只想快速创建一个原型来证明概念,然后再完全移植到iOS。如果dylib可以简单地工作,则更快。因此,本文介绍如何构建和使用dylib,但请注意,它无法获得App Store的批准。(在10.6.4上使用Xcode 3.2.4进行测试)
1. 在属性列表编辑器中打开这些文件:/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX Product Types.xcspec和/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications/iPhone Simulator ProductTypes.xcspec。
2. 在“MacOSX Product Types.xcspec”中找到具有产品类型com.apple.product-type.library.dynamic的项目,并将其拖动到“iPhone Simulator ProductTypes.xcspec”中。

Xcode screenshot 1

3. 打开位于同一位置的“MacOSX Package Types.xcspec”和“iPhone Simulator PackageTypes.xcspec”。
4. 在“MacOSX Product Types.xcspec”中找到具有包类型“com.apple.package-type.mach-o-dylib”的项目,并将其拖动到“iPhone Simulator PackageTypes.xcspec”中。

Xcode screenshot 2

5. 重复“iPhoneOS.platform”的步骤,如果Xcode正在运行,请重新启动。

现在,让我们构建一个dylib。从“Cocoa Touch Static Library”模板开始。该模板应该包括项目中的Foundation.framework。以下是我在模板上进行的更改以构建dylib。

1. 使用文本编辑器打开Xcode项目文件包中的文件project.pbxproj。搜索字符串“producttype”,将其值更改为com.apple.product-type.library.dynamic

现在,使用Xcode打开项目,转到Project->Edit Project Settings

2.Installation Directory”设置为@executable_path/,因为我计划将dylib放在与应用程序可执行文件相同的目录中。

3.Mach-O Type”设置为Dynamic Library。

4.Executable Extension”设置为dylib。

5. “可执行前缀”设置为空

6. 添加一个或两个简单的方法到库中并进行构建。

现在,创建一个测试它的应用程序。这次,我选择了“基于视图”的应用程序。连接一个UIButton和一个UILabel来调用lib并显示返回消息。您可以下载完整的TestApp项目并进行操作。

失落的知识: 下面的屏幕截图与现在不工作的链接有关。 在iOS上构建和使用dylib 输入图像描述 输入图像描述


2
从XCode 4.5起,这些文件可以在以下位置找到(例如):/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications - Chris Devereux
@ChrisDevereux,谢谢!我添加了一条注释以检查您的评论是否有最新路径...当然,这可能会在将来的版本中再次更改 :) - Nate
3
这个答案需要更多的赞同(并且应该成为被采纳的答案,但我怀疑用户510951会在离开Stack Overflow两年后回来)。非常好的答案,Nate! - chown
1
应该有某种主控覆盖,如果@chown说一个答案是正确的...那它就是真正正确的。 - Tim
@Panagiotis,请发布一个新问题,这样可以得到适当的解答。请展示你正在使用的代码和所有的错误信息。如果你愿意,你也可以链接回这个问题/答案。如果你添加“iphone-privateapi”标签,我会看到它。你应该声明这不是为了应用商店,否则人们可能会投票关闭这个问题。 - Nate

114
在提问时,iOS不支持动态库,否则您的应用程序将被拒绝。只有静态库是允许的。
然而,在iOS8中,你可以使用动态库和框架。这应该是“只需运行”的。

17
有人知道为什么吗?对我来说,这似乎完全疯狂。 - Erik de Castro Lopo
77
@Erik de Castro Lopo:原因是安全性:由于动态库可以在运行时加载和卸载,您可以下载其他可执行代码并加载它(考虑插件)。黑客可能会对此进行攻击,然后在您的手机上执行恶意代码是非常糟糕的事情。这也可能使得在已批准的应用程序中添加未经批准的功能成为可能。简而言之,在这种环境下,苹果认为动态链接是一个必须严格控制的潘多拉魔盒,否则它可能会危及安全,我同意这确实有道理在手机上 - DarkDust
7
我正在开发一款内部应用程序,该应用程序不会通过AppStore进行分发,因此我不关心苹果对AppStore的限制。在技术上,是否有可能为iOS应用程序创建动态库? - Aliaksei
3
从技术上讲,是的,否则您将无法链接到苹果库。据我所知,动态库支持与Mac OS X大致相同。然而,Xcode不支持它,但似乎可以使用bundles。请参阅此文章。 - DarkDust
3
不支持与不允许并不相同。 - dtech
显示剩余7条评论

0

从Xcode 11.4.1开始,不允许使用动态库(您的项目将无法编译所有目标)。使用库/框架的新方法是使用xcodebuild创建xcframework。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接