我正在尝试为iOS应用程序制作动态框架.感谢新版本的Xcode(6),我们可以在创建新项目时选择Cocoa Touch Framework,不再需要添加聚合目标,运行脚本等等.构建框架时我没有问题.但是当我尝试在iOS应用程序中使用它时,我遇到了一些架构问题.
ld: warning: ignoring file /Library/Frameworks/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (arm64): /Library/Frameworks/MyFramework.framework/MyFramework Undefined symbols for architecture arm64: "_OBJC_CLASS_$_MyFrameworkWebService", referenced from: objc-class-ref in AppDelegate.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) ld: warning: ignoring file /Library/Frameworks/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (armv7): /Library/Frameworks/MyFramework.framework/MyFramework Undefined symbols for architecture armv7: "_OBJC_CLASS_$_MyFrameworkWebService", referenced from: objc-class-ref in AppDelegate.o ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
好吧,我试图改变框架项目和目标的设置(仅架构和构建有效架构和有效架构).我为iOS应用程序项目做了同样的事情,但没有任何作用.我觉得有些事我不明白.
例如,当我仅使用命令行"xcrun lipo -info MyFramework"检查i386(iOS模拟器)的框架时,我遇到了一个问题
ld:警告:忽略文件/Library/Frameworks/MyFramework.framework/MyFramework,文件是为x86_64构建的,它不是被链接的架构(i386)...
如果有人可以帮助我获得适用于所有iOS架构(包括模拟器)的框架.
我这样做的方式类似于vladof,但希望有点简单.我将框架作为app项目的子项目.
框架项目
创建一个新的iOS Cocoa Touch Framework.称之为MyLib.这将创建一个MyLib.h
添加一个简单的Cocoa Touch Obj-C类,MyClass(.h和.m),并在.m的实现中,创建一个返回字符串的方法, - (NSString*)greetings;
在MyLib.h中,在底部附近添加#import"MyClass.h"
在目标的Build Phases/Headers部分中,将MyClass.h从Project部分移动到Public部分.
做一个构建(cmd-B)
关闭项目
应用项目
创建一个新的单视图应用程序项目,Swift或Obj-C.称之为MyApp.
从Finder中,将MyLib项目文件拖到MyApp窗口的左侧管理器部分,并确保插入行位于MyApp下方.这使得MyLib成为MyApp的子项目.(它仍然可以在其他项目中以相同的方式使用)
单击组织器中的MyApp,然后选择MyApp目标并选择Build Phases.
在Target Dependancies中,单击+号并添加MyLib.
在Link with Libraries中,单击+号并添加MyLib.framework.
对于Obj-C应用程序
在ViewController.m中,添加#import
在viewDidLoad中,添加以下行:
MyLib*x = [[MyLib alloc] init];
NSLog(@"%@",x.greetings);
运行该项目,您应该在调试窗口中看到该消息. -
对于Swift应用程序
在ViewController.swift中,添加import MyLib
在viewDidLoad中,添加以下行:
var x:MyLib = MyLib()
println("(x.greetings())") -
通过这种方式,应用程序依赖于框架,因此如果您在框架类中进行更改,则不必更改目标以单独构建框架,它将首先编译框架,然后是应用程序.
基于所有的响应,上raywenderlich.com岗位和要旨所创造克里斯·康威我想出了这个.
执行以下步骤,我能够构建一个Cocoa Touch框架(包括Swift和Objective-C文件),其中包含模拟器和设备的所有体系结构:
在框架的项目中创建一个新的(聚合)目标
在"Build Phases"下,选择"Add Run Script"并复制该文件的内容
选择的总目标在方案选择下拉
构建的目标 为在总方案
希望能帮助到你 :)
更新:修复了步骤#3中路径不正确的要点中的错误.感谢Tokuriku !!
更新 在Xcode 7和8中,单击文件>新建>目标...然后选择"其他"组以选择聚合目标
设置ONLY_ACTIVE_ARCH=NO
在Build Settings
项目中.
为模拟器构建库
为设备构建库
在Products
框架的控制台文件夹中 打开(可以通过打开框架文件夹打开它,然后cd ..
从那里打开)
从文件夹运行此脚本Products
.它在此文件夹中创建fat Framework.(或按照以下4中的说明手动完成.5.)
framework_name="${$(basename $(find ./Debug-iphoneos -type d -name '*.framework' -maxdepth 1))%.*}" && \ cp -R Debug-iphoneos/$framework_name.framework ./$framework_name.framework && \ lipo -create -output "$framework_name.framework/$framework_name" "Debug-iphonesimulator/$framework_name.framework/$framework_name" "Debug-iphoneos/$framework_name.framework/$framework_name"
要么:
通过此脚本使用lipo组合这两个框架(替换YourFrameworkName
为您的框架名称)
lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
替换为现有框架的新二进制文件:
cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
利润:./YourFrameworkName.framework
- 是现成的胖二进制!您可以将其导入您的项目!
对于项目,不在xcworkspace
-es中:
您也可以尝试使用这个要点但似乎它不适用于工作空间中的项目.
我已经改变了某人的脚本以支持所有Simulator的架构:
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal # make sure the output directory exists mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" # Step 1. Build Device and Simulator versions xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator VALID_ARCHS="x86_64 i386" BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build # Step 2. Copy the framework structure to the universal folder cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/" # Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}" # Step 4. Convenience step to copy the framework to the project's directory cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}" # Step 5. Delete temporary build directory in the project's directory rm -rf "${PROJECT_DIR}/build" # Step 6. Convenience step to open the project's directory in Finder open "${PROJECT_DIR}"
请尝试以下步骤来创建包含框架项目和应用程序项目的工作区.
工作区:
创建工作区.
框架项目:
在Workspace中创建一个iOS Cocoa touch Framework项目.
添加一个简单的Objective C类MyClass(头.h和实现文件.m),并创建一个方法- (void)问候语.
转到项目构建阶段 > 标题 >将MyClass.h从Project移动到Public.
将方案更改为框架项目并选择iOS模拟器,然后构建.(如果集成此框架的应用程序在设备上运行,请选择iOS设备.我将继续在此示例中使用模拟器)
您应该没有问题构建,框架构建可以在您的派生数据目录中找到,您可以在管理器中找到它.
应用项目:
在Workspace中创建Swift Single View应用程序.
将iOS模拟器框架构建(在Debug-iphonesimulator或Release-iphonesimulator中找到)拖到项目上方.
创建一个桥接头来向Swift公开Objective C类方法.
在桥接头文件中导入MyClass.h.
请注意,如果找不到MyClass定义,则添加框架Headers路径到Build Settings Header Search Paths.
在ViewController.swift的 viewDidLoad中创建MyClass的实例,然后调用问候语.
将框架添加到Target> Embedded Binaries
将方案更改为app project并选择iOS模拟器,然后构建.
您应该能够看到问候消息.
请注意,上面的示例演示了如何构建在模拟器中运行的应用程序.如果您需要创建在模拟器和设备上运行的通用静态库,那么一般步骤如下:
为模拟器构建库
为设备构建库
使用lipo将它们结合起来
有关于它在网络上很好的参考,在这里的例子.
为框架创建通用二进制文件:导航到框架Derived Data目录然后/ Build/Products,以下命令可以帮助您在Products目录中创建通用二进制文件:
lipo -create -output "framework-test-01-universal" "Debug-iphonesimulator/framework-test-01.framework/framework-test-01" "Debug-iphoneos/framework-test-01.framework/framework-test-01"
请注意,framework-test-01是我的框架项目名称.