将 iOS 应用与自定义框架关联时出现问题
Problems linking iOS app with custom framework
我将一个较大的 iOS 应用拆分成几个框架,我面临以下问题:
如何正确地将自定义 Cocoa Touch 框架项目包含到 iOS 应用程序项目中,以便一切 link 正确?
- 我已经创建了一个项目框架,里面有所有必要的代码。
- 为了进行测试,我创建了一个示例工作区,并向其中添加了框架项目。
- 接下来,我创建了一个示例 iOS 应用程序项目,其中包含几行使用该框架的代码,并将该项目也添加到工作区。
现在,我进入 linking 部分。
第一次尝试:
在 Xcode、select Info
窗格中打开应用程序目标设置,并在 Linked Frameworks and Libraries
部分添加框架。
为了好看,我也select应用项目中新添加的框架,并将它的Location
从Relative to Group
更改为Relative to Build Products
.位置下方显示为../Debug-iphonesimulator/MyFramework.framework
当前方案是 <Simulator, Debug>
,我点击 Run
,一切正常 - 应用程序记录它正在使用框架.
现在,我清理构建文件夹,并将方案更改为 <Simulator, Release>
。
接下来,我点击 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 构建风格构建的应用程序的方案时,框架将在与应用程序本身相同的目录中以相同的构建风格构建。
我将一个较大的 iOS 应用拆分成几个框架,我面临以下问题:
如何正确地将自定义 Cocoa Touch 框架项目包含到 iOS 应用程序项目中,以便一切 link 正确?
- 我已经创建了一个项目框架,里面有所有必要的代码。
- 为了进行测试,我创建了一个示例工作区,并向其中添加了框架项目。
- 接下来,我创建了一个示例 iOS 应用程序项目,其中包含几行使用该框架的代码,并将该项目也添加到工作区。
现在,我进入 linking 部分。
第一次尝试:
在 Xcode、select
Info
窗格中打开应用程序目标设置,并在Linked Frameworks and Libraries
部分添加框架。为了好看,我也select应用项目中新添加的框架,并将它的
Location
从Relative to Group
更改为Relative to Build Products
.位置下方显示为../Debug-iphonesimulator/MyFramework.framework
当前方案是
<Simulator, Debug>
,我点击Run
,一切正常 - 应用程序记录它正在使用框架.现在,我清理构建文件夹,并将方案更改为
<Simulator, Release>
。接下来,我点击
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 构建风格构建的应用程序的方案时,框架将在与应用程序本身相同的目录中以相同的构建风格构建。