【问题标题】:Problems linking iOS app with custom framework将 iOS 应用程序与自定义框架链接的问题
【发布时间】:2016-07-22 20:26:02
【问题描述】:

我正在将一个较大的 iOS 应用拆分成几个框架,我面临以下问题:

如何正确地将自定义 Cocoa Touch 框架项目包含到 iOS 应用项目中,以便所有内容都能正确链接?

  1. 我创建了一个项目框架,其中包含所有必要的代码。
  2. 为了进行测试,我创建了一个示例工作区,并将框架项目添加到其中。
  3. 接下来,我创建了一个示例 iOS 应用项目,其中包含几行使用框架的代码,并将该项目也添加到了工作区。

现在,我进入链接部分。

第一次尝试:

  1. 在 Xcode 中打开应用目标设置,选择 Info 窗格,然后在 Linked Frameworks and Libraries 部分添加框架。

  2. 为了好看,我还在app项目中选择了新添加的框架,将LocationRelative to Group改为Relative to Build Products。位置下方显示为../Debug-iphonesimulator/MyFramework.framework

  3. 当前方案是<Simulator, Debug>,我点击了Run,并且一切正常 - 应用程序记录它正在使用框架正常

    李>
  4. 现在,我清理构建文件夹,并将方案更改为<Simulator, Release>

  5. 接下来,我点击Run,项目开始构建,然后应用链接失败

Undefined symbols for architecture x86_64: <a function from the framework> referenced from: <a file in the app>.

在检查 build 文件夹时,我可以看到框架已正确构建,位于 .../Build/Products/Release-iphonesimulator/...,并且是一个包含 i386 和 x86_64 的胖二进制文件。

我应该如何继续正确链接框架,以便它在任何配置(调试、发布)以及模拟器和设备上都能正常工作?

为了澄清,我打算同时开发框架和应用程序,所以像这样的解决方案。 CocoaPods 通过预先构建胖框架一次来做到这一点,似乎不太实用(除非我错过了一些东西,因为缺乏足够的 CocoaPods 经验)。


下面是失败的Link 相位输出:

Ld /Users/me/Library/Developer/Xcode/DerivedData/MyWorkspace-ahzqvfgoxbedpudjdhtqudgqzwba/Build/Intermediates/MyApp.build/Release-iphonesimulator/MyApp.build/Objects-normal/x86_64/MyApp normal x86_64
    cd /some/where/here/lives/the/workspace
    export IPHONEOS_DEPLOYMENT_TARGET=9.3
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
      -arch x86_64
      -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.3.sdk
      -L/Users/me/Library/Developer/Xcode/DerivedData/MyWorkspace-ahzqvfgoxbedpudjdhtqudgqzwba/Build/Products/Release-iphonesimulator
      -F/Users/me/Library/Developer/Xcode/DerivedData/MyWorkspace-ahzqvfgoxbedpudjdhtqudgqzwba/Build/Products/Release-iphonesimulator
      -filelist /Users/me/Library/Developer/Xcode/DerivedData/MyWorkspace-ahzqvfgoxbedpudjdhtqudgqzwba/Build/Intermediates/MyApp.build/Release-iphonesimulator/MyApp.build/Objects-normal/x86_64/MyApp.LinkFileList
      -Xlinker
      -rpath
      -Xlinker @executable_path/Frameworks
      -mios-simulator-version-min=9.3
      -Xlinker
      -objc_abi_version
      -Xlinker 2
      -fobjc-arc
      -fobjc-link-runtime
      -stdlib=libc++
      -framework MyFramework 
      -Xlinker
      -dependency_info
      -Xlinker /Users/me/Library/Developer/Xcode/DerivedData/MyWorkspace-ahzqvfgoxbedpudjdhtqudgqzwba/Build/Intermediates/MyApp.build/Release-iphonesimulator/MyApp.build/Objects-normal/x86_64/MyApp_dependency_info.dat
      -o /Users/me/Library/Developer/Xcode/DerivedData/MyWorkspace-ahzqvfgoxbedpudjdhtqudgqzwba/Build/Intermediates/MyApp.build/Release-iphonesimulator/MyApp.build/Objects-normal/x86_64/MyApp

Undefined symbols for architecture x86_64:
  "SomeFancyFuncFromTheFramework()", referenced from:
      -[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o

【问题讨论】:

  • 您是否在App的目标中添加了构建依赖以首先构建框架?
  • NSGod,我确实尝试过,但它只显示了一行 - 应用程序项目名称;没有什么可供选择的,也没有关于框架目标的任何内容。
  • MyApp_dependency_info.dat 文件(来自最后一个-Xlinker 参数)包含对MyFramework.framework/MyFramework.tbdMyFramework.framework/MyFramework 的引用,两者都在.../Build/Products/Release-iphonesimulator/ 中,据我所知(和FWIW)。
  • 嗯,这很奇怪。我整天都在一个 iOS 应用程序上工作,我在做这件事,它工作正常,但现在我刚刚创建了 2 个快速测试项目,它似乎没有像它应该的那样工作(我没有像你一样列出任何东西当我尝试将框架目标添加为依赖项时)......不确定发生了什么......
  • 好吧,终于让它工作了,虽然它需要一些工作。我退出了 Xcode 几次,当我重新打开项目时,情况似乎好了一些。打算从头开始,看看能不能再做一次......

标签: xcode ios-frameworks


【解决方案1】:

首先,创建 iOS 框架项目,确保将框架目标的 Installation Directory (INSTALL_PATH) 构建设置设置为 @rpath。我会更改 Xcode 方案以使其成为共享方案。现在关闭框架项目,以确保在我们按照以下步骤将其导入 App 项目时可以将其打开。

接下来,创建 iOS App 项目。与您的做法类似,我创建了一个App (Debug) 方案和一个App (Release) 方案。我在 App 项目中创建了一个Frameworks 组,如下图所示。然后我找到了我刚刚创建的框架的.xcodeproj 文件,并将它拖到了Frameworks 组中。打开显示三角形以显示框架项目的Products,如下图所示。将其拖到应用目标的General 部分中的Embedded Binaries 部分。这样做应该会自动添加您需要采取的其他步骤以使事情正常工作(我相信这些步骤包括将 framewokr 添加为依赖项、链接到框架以及将框架复制到构建的应用程序中)。

最后一步是确保可以在编译时找到框架。在应用程序目标的构建设置中,确保将Framework Search Paths (FRAMEWORK_SEARCH_PATHS) 设置为$(BUILT_PRODUCTS_DIR)。当您为以 Develop 构建样式构建的应用选择方案时,框架将在与应用本身相同的目录中以相同的构建样式构建。

【讨论】:

  • NSGod,感谢您的回答。现在看起来好多了——项目文件里面没有对“Debug-iphonesimulator”的引用,而且作为奖励,不需要显式的工作区。但是,当将应用程序的方案从调试切换到发布时,我仍然遇到相同的链接问题。
  • 将框架的运行方案切换到发布没有帮助,奇怪。
  • 另一个更新:它与一个虚拟框架项目一起工作,就像你描述的那样。进一步挖掘以找出原始框架不起作用的原因。
  • 所以违规者是框架的 Release xcconfig 中的GCC_SYMBOLS_PRIVATE_EXTERN = YES。谢谢你的帮助,马克。
猜你喜欢
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多