您可以为iOS构建动态库并在运行时加载它们吗?


114

iOS(iPhone / iPad)是否支持动态库?

在Xcode中,我尝试创建一个新项目 -> 框架和库 -> 可可库(动态)。在项目设置中,我将Base SDK设置为,iOS device 4.1并将目标设置为iOS4.1,但是它具有构建错误:

目标指定了产品类型“ com.apple.product-type.library.dynamic”,但“ iphonesimulator”平台没有此类产品类型。”

我选择的构建是Simulator-> Debug-> i386



4
iOS8 +支持基于共享库的框架。
2014年

1
@Eonil,您能详细说明一下吗?我想了解更多有关该文章的信息或链接,将不胜感激。
Maxim Chetrusca 2014年

Answers:


105

在提出此问题时,iOS不支持动态库,这将导致您的应用被拒绝。仅允许使用静态库。

但是,在iOS8中,您可以使用动态库和框架。它应该“正常工作”


14
有人知道为什么吗?在我看来,这简直是疯了。
Erik de Castro Lopo

73
@Erik de Castro Lopo:原因是安全性:由于可以在运行时加载和卸载动态库,因此您可以下载其他可执行代码并进行加载(请考虑使用插件)。这可能会被黑客攻破,然后在手机上执行恶意代码是一件很糟糕的事情。还可以将未经批准的功能添加到批准的应用程序。简而言之:在这种环境下,Apple认为动态链接是必须严格控制的Pandoras盒子,否则它可能会损害安全性,我同意在电话上确实有意义。
DarkDust

6
我正在开发一个内部应用程序,该应用程序不会通过AppStore分发,因此我不在乎Apple对AppStore的限制。从技术上讲,可以为iOS应用创建动态库吗?
Aliaksei

3
@Aliaksei:从技术上讲,是的,否则您将无法链接到Apple的图书馆。AFAIK动态库支持与Mac OS X上几乎相同。但是,Xcode不支持它,但是似乎可以使用捆绑软件。看到这篇文章
DarkDust 2011年

3
不支持与不允许不一样。
dtech

162

我并不是真的不同意DarkDust的回答,但是如果我可以传达我内心的Bill Clinton,这取决于所支持的含义是 :)

苹果公司不希望您对App Store应用程序执行此操作,但是操作系统肯定允许这样做。越狱应用程序始终使用这种技术。基本上,您使用标准的UNIX技术动态地打开框架/库,然后在其中使用内容。该dlopen的功能,您可以通过在传递给打开库的路径框架,或dylib。在一些用于构建越狱应用程序的文档中,以下是一个调用init()在您自己的单独dylib中实现的函数的示例:

#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);
    }
}

此外,默认的限制(不允许您为iOS 构建动态库项目)是Xcode中的功能,您可以通过编辑一些XCode xml文件来覆盖它:

在iOS上构建和使用dylib

完成此操作后,您可以构建普通的iOS .dylib库,并按照上面的示例代码使用它。(是的,每当您安装新的XCode版本时,您可能都必须再次解锁此功能)。

因此,这不是技术限制,而是App Store政策限制。如果您不限于App Store,那么可以做到。请注意,这种技术并没有要求越狱,但如果应用程序是沙箱,它可能会限制地方 dylibs可以被加载。

编辑:为了确保此信息不会丢失给将来的链接腐烂,这是我提供的有关如何在Xcode中启用iOS dylib的链接的内容。(注意:此过程仍适用于Xcode 4,但请参见下面的注释,以获取路径的更新等信息。) iOS Place博客


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产品Types.xcspec/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications / iPhone模拟器ProductTypes.xcspec

2.在“ MacOSX Product Types.xcspec ”中找到具有该产品类型的项目,com.apple.product-type.library.dynamic然后将其拖到“ iPhone Simulator ProductTypes.xcspec ”中。

Xcode屏幕截图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屏幕截图2

5.对“ iPhoneOS.platform ” 重复上述步骤,然后重新启动Xcode(如果正在运行)。

现在,让我们构建一个dylib。从“ Cocoa Touch Static Library ”模板开始。那应该在项目中包含Foundation.framework。这是我在模板顶部进行的用于构建dylib的更改。

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

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

2.之所以将“ 安装目录 ”设置为@executable_path/是因为我计划将dylib与该应用程序的可执行文件放在同一目录中。

3.将Mach-O类型 ”设置为动态库

4.将可执行扩展名 ”设置为dylib

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

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

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


2
从XCode 4.5开始,这些文件可以在(例如)/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications中找到-Chris
Devereux

@ChrisDevereux,谢谢!我放了一条便条以检查您对最新路径的评论...当然,将来的版本中可能会再次更改:)
Nate 2012年

3
该答案需要更多投票(并且确实应该是公认的答案,但是我怀疑user510951在离开SO两年后会回来的)。内特很好的回答!
chown 2012年

1
如果@chown说答案是正确的,那么应该有某种主控权改写了……该死的是正确的。
蒂姆(Tim)

@Panagiotis,请发布一个新问题,以便可以正确解决。显示您正在使用的代码以及所有错误消息。如果需要,您还可以链接回该问题/答案。如果添加“ iphone-privateapi”标签,我会看到它。您应声明此内容不适用于应用商店,否则人们可能会投票关闭该问题。
Nate

0

从Xcode 11.4.1开始,不允许使用动态库(您的项目不会针对所有目的地进行编译)。使用libs / frameworks的新方法是xcodebuild中的create-xcframework。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.