将 iOS 应用与自定义框架关联时出现问题

Problems linking iOS app with custom framework

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

如何正确地将自定义 Cocoa Touch 框架项目包含到 iOS 应用程序项目中,以便一切 link 正确?

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

现在,我进入 linking 部分。

第一次尝试:

  1. 在 Xcode、select Info 窗格中打开应用程序目标设置,并在 Linked Frameworks and Libraries 部分添加框架。

  2. 为了好看,我也select应用项目中新添加的框架,并将它的LocationRelative to Group更改为Relative to Build Products.位置下方显示为../Debug-iphonesimulator/MyFramework.framework

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

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

  5. 接下来,我点击 Run,项目开始构建,然后 app linking 失败 :

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

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

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

澄清一下,我打算同时开发框架和应用程序,所以像这样的解决方案CocoaPods 通过预先构建 fat 框架一次,似乎不太实用(除非我遗漏了什么,因为缺乏足够的 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

首先,创建 iOS 框架项目,确保将框架目标的 Installation Directory (INSTALL_PATH) 构建设置设置为 @rpath。我会更改 Xcode 方案,使其成为共享方案。现在关闭framework项目,以确保我们在后面的步骤中将其导入到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)。当您 select 以 Develop 构建风格构建的应用程序的方案时,框架将在与应用程序本身相同的目录中以相同的构建风格构建。