iOS 【私有库】模拟真机合并

下面我们用系统自带的来新建.framework.然后再添加一个依赖库 AFNetworking

  1. xcode的菜单栏 File -> New Project 建立一个名为 YohunlUtilsLib 的Cocoa Touch Framework的工程. 将Target 改为 7.0(由于现在大多数应用都还要支持7.0sdk,故此处我们修改为支持7.0)
    这时候,编译一下,你可能会遇到警告

我们要修改 Mach-O Type.从默认的Dynamic Library 改为 Static Library,再编译,警告消失
Static Library 支持IOS8.0 sdk以下的,从目前来看,大多数工程都还要支持7.0 sdk,所以我们最常用的就是Static Library

命令行,进入目录下 pod init 建立一个podfile文件,因为我们制作的.framework需要用到AFNetworking网络库 PS:你也可以用任意的方式建立这个podfile文件
打开它,因为我采用 pod init命令建立的,打开后你会发现它已经有内容了
再执行 pod install 建立依赖

platform :ios, ‘8.0’
inhibit_all_warnings!

target 'OSUtilsFirstLib' do

pod 'AFNetworking'

end

打开工程,添加一个类TestMode,在其中添加方法(同理添加类AdvModel)

//TestMode.m
#import <Foundation/Foundation.h>

@interface TestMode : NSObject

+ (NSString *)testName:(NSString *)name;
@end

//TestMode.m
#import "TestMode.h"

@implementation TestMode

+ (NSString *)testName:(NSString *)name {
   return [NSString stringWithFormat:@"test:----%@",name];
}
@end

//创建一个带网络请求的 类

#import <Foundation/Foundation.h>
@interface YONetwork : NSObject
// 需要 pod AFNetworking

- (void)getGithubReposForUser:(NSString*)user withSuccess:(void(^)(id responseObject))success failure:(void(^)(NSError*error))failure;
- (void)test;
@end

//  YONetwork.m
#import "YONetwork.h"
#import "AFNetworking.h"

@implementation YONetwork

- (void)getGithubReposForUser:(NSString*)user withSuccess:(void(^)(id responseObject))success failure:(void(^)(NSError*error))failure
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager GET:@"https://www.baidu.com" parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    }
         success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
             NSLog(@"这里打印请求成功要做的事");
         }
         failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull   error) {
             NSLog(@"%@",error);  //这里打印错误信息
         }];
}
- (void) test {
    [self getGithubReposForUser:@"occ"withSuccess:^(id responseObject) {
        NSLog(@"getGithubReposForUser response = %@",responseObject);
    } failure:^(NSError*error) {
        NSLog(@"getGithubReposForUser error = %@",error);
    }];
}
@end

私有库里的文件头设置

//  OSUtilsFirstLib.h
#import <UIKit/UIKit.h>
FOUNDATION_EXPORT double OSUtilsFirstLibVersionNumber;
FOUNDATION_EXPORT const unsigned char OSUtilsFirstLibVersionString[];
// 设置开放的头文件
#import  <OSUtilsFirstLib/YONetwork.h>
6DBF4EB1-E565-42C0-9329-02EE38880820.png

编译运行 (command + B),生成相应的.framework文件(先选择模拟器,编译,在选择真机,编译)
~/资源库/Developer/Xcode/DerivedData/ 找到 OSUtilsFirstLib 或 在库上右键Show in Finder

434C53BB-3D81-4B73-9B35-DD899E2DB77E.png

可以看到目录结构如下:

B672600D-38AE-4CCF-8613-C61D0028A932.png

查看静态库支持的CPU架构

➜  Release-iphoneos git:(master) ✗ lipo -info OSUtilsFirstLib.framework/OSUtilsFirstLib
Architectures in the fat file: OSUtilsFirstLib.framework/OSUtilsFirstLib are: armv7 arm64 

说明我们生成的真机framework: OSUtilsFirstLib.framework 包含了两种架构 armv7 arm64

我们使用命令来合并我们生成的真机和模拟器的framework

1、建立一个新的target(Aggregate)


54F73597-C916-4B83-AC01-89A6B6158684.png

2、选择Target ——> 【+】号———>【New Run Script Phase]


64FF1B25-5B0A-428D-ADAC-26631CFE6C6B.png

添加如下的合并模拟器和真机的脚本(【Run Script 】添加脚本)

4749B363-E0AE-4BCA-B2F2-F22EFE7DBDD5.png

私有库.framework合并(coocaPods项目)

if [ "${ACTION}" = "build" ]
then


####### PROJECT_NAME = OSUtilsFirstLib
#要build的target名
target_Name=${PROJECT_NAME}
echo "target_Name=${target_Name}"


######## SRCROOT = /Users/occ/Desktop/组件化/私有库2/OSUtilsFirstLib2
#build之后的文件夹路径
build_DIR=${SRCROOT}/build
echo "build_DIR=${build_DIR}"

#真机build生成的.framework文件路径
BUILD_DEVICE_DIR_F=${build_DIR}/Build/Products/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
echo "BUILD_DEVICE_DIR_F=${BUILD_DEVICE_DIR_F}"

#模拟器build生成的.framework文件路径
BUILD_SIMULATOR_DIR_F=${build_DIR}/Build/Products/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
echo "BUILD_SIMULATOR_DIR_F=${BUILD_SIMULATOR_DIR_F}"


#合并目标文件夹路径
RESULT_DIR_F=${SRCROOT}/Products/${PROJECT_NAME}
echo "RESULT_DIR_F=${RESULT_DIR_F}"

#合并目标路径(合并的包替换目标文件.framework中对应的包)
#└── OSUtilsFirstLib.framework
#    ├── Headers
#    ├── Info.plist
#    ├── Modules
#    ├── OSUtilsFirstLib (替换这个)
#    └── PrivateHeaders

RESULT_DIR_F_A=${SRCROOT}/Products/${PROJECT_NAME}/${PROJECT_NAME}.framework/${PROJECT_NAME}
echo "RESULT_DIR_F_A=${RESULT_DIR_F_A}"

#判断build文件夹是否存在,存在则删除
if [ -d "${build_DIR}" ]
then
rm -rf "${build_DIR}"
fi

#判断合并目标文件夹是否存在,存在则删除该文件夹
if [ -d "${RESULT_DIR_F}" ]
then
rm -rf "${RESULT_DIR_F}"
fi
#创建目标文件夹
mkdir -p “${RESULT_DIR_F}"

#build之前clean一下
# ============================== build之前clean一下 =============================#

xcodebuild -target ${target_Name} clean

####PROJECT_FILE_PATH = /Users/occ/Desktop/组件化/私有库2/OSUtilsFirstLib2/OSUtilsFirstLib.xcodeproj
#### CONFIGURATION = Debug

# ============================== build(带有Pods的) =============================#
#模拟器build
xcodebuild -workspace "${target_Name}.xcworkspace" -scheme "${target_Name}" -configuration "${CONFIGURATION}" -sdk iphonesimulator -derivedDataPath "${build_DIR}"

#真机build
xcodebuild -workspace "${target_Name}.xcworkspace" -scheme "${target_Name}" -configuration "${CONFIGURATION}" -sdk iphoneos -derivedDataPath "${build_DIR}"

# 直接换成模拟与真机的
#xcodebuild -workspace "${target_Name}.xcworkspace" -scheme "${target_Name}" -configuration "${CONFIGURATION}" -derivedDataPath "${build_DIR}" ONLY_ACTIVE_ARCH=NO || exit

#复制真机build的framework文件到目标文件夹
cp -R "${BUILD_DEVICE_DIR_F}" “${RESULT_DIR_F}"

# ======================= 合成模拟器和真机.framework包=========================== #
echo "真机build生成的.framework文件路径=${BUILD_DEVICE_DIR_F}/${PROJECT_NAME}"
echo "模拟器build生成的.framework文件路径=${BUILD_SIMULATOR_DIR_F}/${PROJECT_NAME}"

#/Users/occ/Desktop/组件化/私有库2/OSUtilsFirstLib2/build/Build/Products/Release-iphoneos/OSUtilsFirstLib.framework/OSUtilsFirstLib
#/Users/occ/Desktop/组件化/私有库2/OSUtilsFirstLib2/build/Build/Products/Release-iphonesimulator/OSUtilsFirstLib.framework/OSUtilsFirstLib


#(合并的包替换目标文件.framework中对应的包)
#└── OSUtilsFirstLib.framework
#    ├── Headers
#    ├── Info.plist
#    ├── Modules
#    ├── OSUtilsFirstLib (替换这个)
#    └── PrivateHeaders
lipo -create "${BUILD_DEVICE_DIR_F}/${PROJECT_NAME}" "${BUILD_SIMULATOR_DIR_F}/${PROJECT_NAME}" -output "${RESULT_DIR_F_A}"

#打开目标文件夹
open "${RESULT_DIR_F}"
fi

静态库.a文件合成(非coocaPods项目)

if [ "${ACTION}" = "build" ]
then


#要build的target名
target_Name=${PROJECT_NAME}
echo "target_Name=${target_Name}"


#build之后的文件夹路径
build_DIR=${SRCROOT}/build
echo "build_DIR=${build_DIR}"

#真机build生成的头文件的文件夹路径
DEVICE_DIR_INCLUDE=${build_DIR}/Release-iphoneos/include/${PROJECT_NAME}
echo "DEVICE_DIR_INCLUDE=${DEVICE_DIR_INCLUDE}"

#真机build生成的.a文件路径
DEVICE_DIR_A=${build_DIR}/Release-iphoneos/lib${PROJECT_NAME}.a
echo "DEVICE_DIR_A=${DEVICE_DIR_A}"

#模拟器build生成的.a文件路径
SIMULATOR_DIR_A=${build_DIR}/Release-iphonesimulator/lib${PROJECT_NAME}.a
echo "SIMULATOR_DIR_A=${SIMULATOR_DIR_A}"


#目标文件夹路径
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}
echo "INSTALL_DIR=${INSTALL_DIR}"

#目标头文件文件夹路径
INSTALL_DIR_Headers=${SRCROOT}/Products/${PROJECT_NAME}/Headers
echo "INSTALL_DIR_Headers=${INSTALL_DIR_Headers}"

#目标.a路径
INSTALL_DIR_A=${SRCROOT}/Products/${PROJECT_NAME}/lib${PROJECT_NAME}.a
echo "INSTALL_DIR_A=${INSTALL_DIR_A}"

#判断build文件夹是否存在,存在则删除
if [ -d "${build_DIR}" ]
then
rm -rf "${build_DIR}"
fi

#判断目标文件夹是否存在,存在则删除该文件夹
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
#创建目标文件夹
mkdir -p "${INSTALL_DIR}"


#build之前clean一下
xcodebuild -target ${target_Name} clean

#模拟器build
xcodebuild -target ${target_Name} -configuration Release -sdk iphonesimulator

#真机build
xcodebuild -target ${target_Name} -configuration Release -sdk iphoneos

#复制头文件到目标文件夹
cp -R "${DEVICE_DIR_INCLUDE}" "${INSTALL_DIR_Headers}"

#合成模拟器和真机.a包
lipo -create "${DEVICE_DIR_A}" "${SIMULATOR_DIR_A}" -output "${INSTALL_DIR_A}"

#打开目标文件夹
open "${INSTALL_DIR}"
fi

静态库.a文件合成(coocaPods项目)

if [ "${ACTION}" = "build" ]
then

#要build的target名
target_Name=${PROJECT_NAME}
echo "target_Name=${target_Name}"

#build之后的文件夹路径
build_DIR=${SRCROOT}/build
echo "build_DIR=${build_DIR}"

#真机build生成的头文件的文件夹路径
DEVICE_DIR_INCLUDE=${build_DIR}/Build/Products/Release-iphoneos/include/${PROJECT_NAME}
echo "DEVICE_DIR_INCLUDE=${DEVICE_DIR_INCLUDE}"

#真机build生成的.a文件路径
DEVICE_DIR_A=${build_DIR}/Build/Products/Release-iphoneos/lib${PROJECT_NAME}.a
echo "DEVICE_DIR_A=${DEVICE_DIR_A}"

#模拟器build生成的.a文件路径
SIMULATOR_DIR_A=${build_DIR}/Build/Products/Release-iphonesimulator/lib${PROJECT_NAME}.a
echo "SIMULATOR_DIR_A=${SIMULATOR_DIR_A}"


#目标文件夹路径
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}
echo "INSTALL_DIR=${INSTALL_DIR}"

#目标头文件文件夹路径
INSTALL_DIR_Headers=${SRCROOT}/Products/${PROJECT_NAME}/Headers
echo "INSTALL_DIR_Headers=${INSTALL_DIR_Headers}"

#目标.a路径
INSTALL_DIR_A=${SRCROOT}/Products/${PROJECT_NAME}/lib${PROJECT_NAME}.a
echo "INSTALL_DIR_A=${INSTALL_DIR_A}"

#判断build文件夹是否存在,存在则删除
if [ -d "${build_DIR}" ]
then
rm -rf "${build_DIR}"
fi

#判断目标文件夹是否存在,存在则删除该文件夹
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
#创建目标文件夹
mkdir -p "${INSTALL_DIR}"


#build之前clean一下
xcodebuild -target ${target_Name} clean

#模拟器build
xcodebuild -workspace "${target_Name}.xcworkspace" -scheme "${target_Name}" -configuration Release -sdk iphonesimulator -derivedDataPath "${build_DIR}"

#真机build
xcodebuild -workspace "${target_Name}.xcworkspace" -scheme "${target_Name}" -configuration Release -sdk iphoneos -derivedDataPath “${build_DIR}"

#复制头文件到目标文件夹
cp -R "${DEVICE_DIR_INCLUDE}" "${INSTALL_DIR_Headers}"

#合成模拟器和真机.a包
lipo -create "${DEVICE_DIR_A}" "${SIMULATOR_DIR_A}" -output "${INSTALL_DIR_A}"

#打开目标文件夹
open "${INSTALL_DIR}"
fi

对于添加的脚本,其中用到了很多的 xcode预定义的变量,这些变量怎么来的呢?你可以在命令行下, 输入

➜  OSUtilsFirstLib git:(master) ✗ xcodebuild -workspace OSUtilsFirstLib.xcworkspace -scheme OSUtilsFirstLib -sdk iphonesimulator -configuration Debug -showBuildSettings > xcodebuild_showBuildSettings.txt

来将所有的xcode预定义变量都导入到文本xcodebuild_showBuildSettings.txt 中,然后你就可以选用你需要的啦

一般都应该合并release模式的,而不是debug模式的framework,设置好后: ccmmand+B 编译

BF13290E-E3D6-4C55-BAA6-093FDEB3E0E2.png

测试:新建一个项目,将合并的OSUtilsFirstLib.framework拖入到项目中,测试


091523FD-D164-4A4F-B027-74C65F7B1C37.png

当我们使用 Dynamic Library模式(只有iOS8.0及以上才支持)的时候.如同普通文件一样添加到示例工程中去的话,
直接运行,会出现提示:,可能会报错:Reason: image not found

选择 TARGETS [SOTestDemo] ——> Build Phases ——> 【+】号 ——> 【New Copy..】——>【Copy Filses】 添加库


4136D563-3F08-4EE0-907F-408D3A244529.png

终端命令

打包Framework,测试时:
1、用模拟器打包,测试时只能跑在模拟器
2、用真机打包,测试时只能跑在真机

解决如下:
1、打开终端
2、输入 lipo -create 【模拟器打包path】 【真机打包path】 -output 【导出兼容版本path】

实现步骤:
1、右击打开包,在finder显示

78429194-A085-4C61-BC7B-5328D177F27C.png

2、正常我们会看到这些,(一般习惯设置成Release环境下),重点是第三个红框,这就是我们要合并的东西。


BB10184A-D40D-4EF0-92C0-17734B19F603.png

3、创建合并文件夹combine
4、合并

F89B0C94-4A07-455E-BBAF-5C8DE81EE019.png
lipo -create /Users/occ/Library/Developer/Xcode/DerivedData/OSUtilsFirstLib-absygfecsqswxbfursvwqzmxpzpo/Build/Products/Release-iphoneos/OSUtilsFirstLib.framework/OSUtilsFirstLib /Users/occ/Library/Developer/Xcode/DerivedData/OSUtilsFirstLib-absygfecsqswxbfursvwqzmxpzpo/Build/Products/Release-iphonesimulator/OSUtilsFirstLib.framework/OSUtilsFirstLib -output /Users/occ/Library/Developer/Xcode/DerivedData/OSUtilsFirstLib-absygfecsqswxbfursvwqzmxpzpo/Build/Products/combine/OSUtilsFirstLib 

5、合并文件夹下会出现一个文件

89718EE2-53D3-4D5C-A2B2-2F41A1D6D1CE.png

私有库合并

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容