cocoapods应用第一部分-xcode创建.framework相关

问题的提出:

随着项目的越来越大,可能会出现好几个团队共同维护一个项目的情况,例如:项目组A负责其中的A块,项目组B负责其中的B块.....这几块彼此之间既独立,也相互联系.对于这种情况,可以采用约定的方式,比如,你只修改你那块,不要修改公共的.如果要修改公共的,那么必须要通知一下其它组,大家共同决定怎么修改,这种方式有一个很大的问题,很有可能不经意间就改了别的团队的代码.还有维护的越来越复杂等.

诸如此类的问题,很自然的我们会考虑每个团队建立一个静态库

IOS的静态库有两种,.a和.framework,  动态库.framework居多.   静态库建议也生成.framework模式的,好处是.framework包含了相关的.h文件等..a文件还要自己添加相关的.h文件

静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝.例如我们在我们的程序中使用了百度地图的.a文件,另外一个应用也使用了百度地图.a.这样整个系统中,会出现两个 百度地图.a文件

动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存.系统提供的库基本上都属于此类,例如UIKit等,A应用和B应用中都用到了UIKit,系统只加载了一份在内存中.IOS中对于第三方的动态库,很遗憾,目前还不支持的.

一:framework的制作

从xcode6开始,已经提供了制作.framework的选项了

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

1) xcode的菜单栏  File -> New Project  建立一个名为  YohunlUtilsLib 的Cocoa Touch Framework的工程. 将Target 改为 7.0(由于现在大多数应用都还要支持7.0sdk,故此处我们修改为支持7.0)

这时候,编译一下,你可能会遇到警告

(null): Embedded dylibs/frameworks only run on iOS 8 or later

别着急,这个是由于 从IOS8开始,建立的framework可以是动态的(并不是完全意义上的动态,这里的动态,其实还是要嵌入到我们的应用中,而不能够从网上下载,然后用dlopen动态加载的).

我们要修改 Mach-O Type.从默认的Dynamic Library 改为 Static Library,再编译,警告消失

那么选择 Dynamic Library 还是   Static Library 有什么影响呢? 我已经实际的检验过了.(我采用了一个包含了 第三方库 AFnetworking的测试工程)

Static Library 支持IOS8.0 sdk以下的,从目前来看,大多数工程都还要支持7.0 sdk,所以我们最常用的就是Static Library

当我们使用   Static Library时候,生成的framework直接如同添加普通文件的形式添加进来就可以了.它会自动在

不过当我们运行的时候,会提示:

当生成后,添加到示例工程中,

好吧,这种模式的添加,看来有些问题呀,还要自己添加依赖库,这些依赖库都是系统的,根据提示自己添加就可以了

再运行,OK

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

dyld: Library not loaded: @rpath/NetTestLib.framework/NetTestLib

Referenced from: /Users/yohunl/Library/Developer/CoreSimulator/Devices/B1DBCA26-C113-4C74-BB81-297D4AF1E0C8/data/Containers/Bundle/Application/C1B4F6D5-96FD-4245-8E6D-4F1C569EEF6F/TestFramework.app/TestFramework

  Reason: image not found

解决的方式

在工程的配置  Embedded Binaries下面添加.而不是在 Linked Frameworks and Libraries下添加.这种方式,不需要添加 AFNetworking所需要的系统库,这一点不知道是什么原因!!!如果有知道原因的,请也告知我一下啊

再运行,OK

2)  命令行,进入目录下  pod init 建立一个podfile文件,因为我们制作的.framework需要用到AFNetworking网络库 PS:你也可以用任意的方式建立这个podfile文件

打开它,因为我采用 pod init命令建立的,打开后你会发现它已经有内容了

修改其内容为

platform :ios, ‘7.0‘

inhibit_all_warnings!

target ‘YohunlUtilsLib‘ do

pod ‘AFNetworking‘

end

target ‘YohunlUtilsLibTests‘ do

end

再执行 pod install 建立依赖

打开工程,添加一个文件  YONetwork.h,在其中添加方法

@interfaceYONetwork :NSObject

/**


获取github上用户的repo

*

*  @paramuser   用户名

*  @paramsuccess成功的回调

*  @paramfailure失败的回调

*/

- (void)getGithubReposForUser:(NSString*)user
withSuccess:(void(^)(idresponseObject))success
failure:(void(^)(NSError*error))failure;

/**


测试 getGithubReposForUser:withSuccess:failure的

*/

- (void)test;

@end

#import"YONetwork.h"

#import
"AFNetworking.h"

@implementationYONetwork

- (void)getGithubReposForUser:(NSString*)user
withSuccess:(void(^)(idresponseObject))success
failure:(void(^)(NSError*error))failure

{

AFHTTPRequestOperationManager
*manager = [AFHTTPRequestOperationManagermanager];

[manager
GET:[NSStringstringWithFormat:@"https://api.github.com/users/%@/repos",
user]
parameters:nilsuccess:^(AFHTTPRequestOperation*operation,id
responseObject) {

success(responseObject);

}
failure:^(AFHTTPRequestOperation*operation,NSError*error)
{

failure(error);

}];

}

- (void) test {

[selfgetGithubReposForUser:@"yohunl"withSuccess:^(idresponseObject)
{

NSLog(@"getGithubReposForUser response = %@",responseObject);

}
failure:^(NSError*error) {

NSLog(@"getGithubReposForUser error = %@",error);

}];

}

@end

编译运行 (command + B),生成相应的.framework文件

菜单 -  organizer

可以看到目录结构如下:

其中的 YohunlUtilsLib.framework 就是我们要的  : 注意,YohunlUtilsLib.framework中并没有包含AFNetworking库的内容,这一点我们可以用如下的命令来验证.

命令进入 Debug-iphoneos

$ lipo -info YohunlUtilsLib.framework/YohunlUtilsLib

输出

Architectures in the fat file: YohunlUtilsLib.framework/YohunlUtilsLib are: armv7 arm64

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

分离出每一种架构

$ mkdir armV7  当前目录建立文件夹,用于存放分离后的架构,和分离出的.o文件

$ lipo YohunlUtilsLib.framework/YohunlUtilsLib -thin armv7 -output ./armv7/YohunlUtilsLib_armv7  分离出armv7架构到文件夹armV7下

$ cd armV7 进入文件夹

$ ar -x YohunlUtilsLib_armv7  分离出armv7架构的所有的.o文件

分离后,如图:

可以看到,最后的.framework中,并没有包含我们pod添加的 AFNetworking.所以 当我们把我们生成的YohunlUtilsLib.framework给别人使用过的时候,别人自己要在项目中添加
AFNetworking,否则会提示找不到的错误
.

验证的方式可以参见 http://jiapumin.iteye.com/blog/2119102  主要是利用命令

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

建立一个新的target

target建立后

添加如下的合并模拟器和真机的脚本

# Constants

SF_TARGET_NAME=${PROJECT_NAME}

#自定义的用来存放最后合并的framework

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

#IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos

WORKSPACE_NAME=${PROJECT_NAME}.xcworkspace

YO_SCHEME=${PROJECT_NAME}

#clean build是先清除原来的build

xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphonesimulator -configuration"${CONFIGURATION}"clean build

xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphoneos -configuration"${CONFIGURATION}"clean build

# build project

#xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64" SYMROOT="${SYMROOT}" ARCHS=‘arm64‘ VALID_ARCHS=‘arm64‘ $ACTION

#xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" 
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/armv7" SYMROOT="${SYMROOT}" ARCHS=‘armv7 armv7s‘ VALID_ARCHS=‘armv7 armv7s‘ $ACTION

# Copy the framework structure to the universal folder (clean it first)

#因为framework的合并,lipo只是合并了最后的二进制可执行文件,所以其它的需要我们自己复制过来

#先移除原来的

rm -rf
"${UNIVERSAL_OUTPUTFOLDER}"

mkdir -p
"${UNIVERSAL_OUTPUTFOLDER}"

cp -R
"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework"
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"

#合并模拟器和真机的架构

lipo -create 
"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}""${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"-output"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

open
"${UNIVERSAL_OUTPUTFOLDER}"

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

xcodebuild -workspace YohunlUtilsLib.xcworkspace -scheme YohunlUtilsLib -sdk iphonesimulator -configuration Debug -showBuildSettings > xcodebuild_showBuildSettings.txt

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

当然了,我们一般都应该合并release模式的,而不是debug模式的framework,这个可以在

ccmmand+B 编译

如果不出错的话,应该会弹出

到此处,我们的framework建立好了,下面可以建立一个测试工程来测试一下,是否可以了

4)建立一个single View Application的测试上述framework的工程 TestFrameworkDemo

将上一步生成的 Release-universal/YohunlUtilsLib.framework 加入到工程 TestFrameworkDemo

再写一个测试用例:

运行,这时候,你会收到错误提示

还记得前面说过吧,我们打包的framework并不包含

此时,我们有两种方式解决这个问题:

1. 将我们生成 YohunlUtilsLib.framework 过程中生成的libAFNetworking.a 拷贝过来,添加到工程中(当然了,你要自己合并 libAFNetworking的真机和模拟器的.a文件) [这种方式的好处是可以保证我们的YohunlUtilsLib.framework使用到的libAFNetworking和我们一样的版本,保证了兼容性,,但同时也增加了集成的复杂性,我们要申明我们的framework用到了哪些第三方和第三方的版本信息]

2.在TestFrameworkDemo 工程中,增加 podFile文件,在其中加入 依赖  pod ‘AFNetworking‘

重新pod install一下 [推荐这种方式,因为,我们用到的第三方都可以使用pod管理,方便],下面就以这种方法来说明

运行,OK!!!

源码在  https://github.com/yohunl/TestFrameworkDemo.git

framework在  https://github.com/yohunl/YohunlUtilsLib.git

二:使用 pod 的命令  pod lib create 来创建 使用pod的framework

采用cocoapods自带的命令,比较方便的http://guides.cocoapods.org/making/using-pod-lib-create 
 例如  pod lib create BZLib.可以自带demo的

命令如下  
pod lib create YohunlUtilsPod

注意:各个版本的cocoapods生成的示例工程结构什么的,会有点不一样,比如最新的带有demo的生成的lib工程就本身就是target的名字,但是之前版本target的名字是 名字_example

pod lib create 工程名  使会让你确认4个问题,由此来建立工程,4个问题都是很简单的,你可以自行选择

注意到了没?这里我们的 YohunlUtilsPod 目录下,并没有podfile文件,那么我们建立的库要怎么依赖第三方的啊.这里就是
YohunlUtilsPod.podspec 文件出场了,在这个文件中,可以制定我们生成的framework依赖于什么.有关于spec文件,是关键文件,原则上,只要我们把这个文件交给别人,别人就可以添加我们的lib到工程里了

编辑YohunlUtilsPod.podspec 文件(此文件实际上是 ruby格式的,如果你用ruby相关的编辑器打开,就能高亮显示了),修改内容为

Pod::Spec.new do |s|

s.name             = "YohunlUtilsPod"

s.version          = "1.0.0"

s.summary          = "测试pod生成framework的YohunlUtilsPod."

s.description      = "测试用的,我们用来测试使用pod
lib create 生成的framework工程"

s.homepage         = "https://github.com/yohunl/YohunlUtilsPod"

# s.screenshots     = "www.example.com/screenshots_1", "www.example.com/screenshots_2"

s.license          = ‘MIT‘

s.author           = { "yohunl" => "[email protected]" }

s.source           = { :git => "https://github.com/yohunl/YohunlUtilsPod.git", :tag => s.version.to_s }

# s.social_media_url = ‘https://twitter.com/<TWITTER_USERNAME>‘

s.platform     = :ios, ‘7.0‘

s.requires_arc = true

s.source_files = ‘Pod/Classes/**/*‘

s.resource_bundles = {

‘YohunlUtilsPod‘ => [‘Pod/Assets/*.png‘]

}

# s.public_header_files = ‘Pod/Classes/**/*.h‘

# s.frameworks = ‘UIKit‘, ‘MapKit‘

s.dependency ‘AFNetworking‘

end

验证podspec文件是否正确是使用命令  在podspec所在目录下执行  pod lib lint

如果提示错误的话,它会给出详细的提示,你照着修改就好了,备注:我已经将源码上传到了github上(你也可以上传你的私有git服务器,一般公司都应该有自己的git服务器)

更改完后,在工程中再加入  YONetwork.h和.YONetwork.m

再运行 pod install

如果提示

SZ-lingdaiping:Example yohunl$ pod install

Updating local specs repositories

Analyzing dependencies

Fetching podspec for `YohunlUtilsPod` from `../`

[!] Unable to satisfy the following requirements:

- `YohunlUtilsPod (from `../`)` required by `Podfile`

- `YohunlUtilsPod (from `../`)` required by `Podfile`

- `YohunlUtilsPod (= 0.1.0)` required by `Podfile.lock`

那么删掉  Podfile.lock文件,因为我们更改了podspec文件里的库的版本号了

看到没,是在 Development Pods文件夹下,因为并没有上传到官方去,所以,在此处是 私有的,所以在Development Pods文件夹下  .

接下来,如同第一个一样,添加一个新的target,添加 run script脚本 ,运行它,得到

建立一个测试工程

注意上面图里面的文字,此处因为我们的framework工程采用dynamic 模式的(上文有论述!!!)  所以需要在Embedded Binaries下添加相应的库.至于为什么还要添加 AFNetworking.framework,上面也有论述,是因为我们打包的.framework并没有包含AFNetworking.framework,如果不加上,运行起来,还是要报错的哦

好了,第一部分讲完了

那么我们怎么使用 像我们使用其它开源库那样的,只要在demo工程里添加一句

pod ‘YohunlUtilsPod‘ 然后pod install一下就可以添加呢?(当然了,这种方式,我们一般是直接源码模式的framework加入demo工程)

这就是第二部分要讲的.

参考文档:

http://maxao.free.fr/xcode-plugin-interface/build-settings.html#variables

ttps://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html

ttp://outofmemory.cn/shell/learn-shell-in-30-minutes/

http://www.cnblogs.com/wendingding/p/3893095.html

http://www.cnblogs.com/brycezhang/p/4117180.html

http://wenva.github.io/2015/07/08/创建自己的CocoaPods私有仓库.html

http://insert.io/framework-ios8-xcode6/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-16 20:32:41

cocoapods应用第一部分-xcode创建.framework相关的相关文章

Xcode 创建.a和framework静态库(转)

最近因为项目中的聊天SDK,需要封装成静态库,所以实践了一下创建静态库的步骤,做下记录. 库介绍 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种.iOS中的静态库有 .a 和 .framework两种形式:动态库有.dylib 和 .framework 形式,后来.dylib动态库又被苹果替换成.tbd的形式. 静态库与动态库的区别 静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库:而动态库在程序

xcode创建一个工程的多个taget,便于测试和发布多个版本

背景:很多时候,我们需要在一个工程中创立多个target,也就是说我们希望同一份代码可以创建两个应用,放到模拟器或者真机上,或者是,我们平时有N多人合作开发,当测试的时候,在A这里装了一遍测A写的那块,当需要测试B写的代码时,我们需要到B那里去装一遍,如果只有一个target的话,那么A的将会被覆盖 还有些时候,我们需要确定到底是A的问题还是B的代码出了问题,这时候都需要建立一个工程能够编译多个版本出来,下文就介绍怎么在一个工程中编译多个版本 好了,闲话不多少,下面正式开始: 我们建立一个默认的

转载《Xcode 创建静态库和动态库》

Xcode 创建静态库和动态库 地址链接   http://www.cocoachina.com/ios/20150921/13385.html 1.linux中静态库和动态库区别: 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. 静态库:这类库的名字一般是libxxx.a:利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去

iOS 32位、 64位系统兼容性设置-Xcode创建支持IOS4.3以上版本的应用的方法

方法一: 如果是Xcode 5的话步骤为 点击项目名称->Build Settings->搜索 Architectures 这个里面的原始的值是Standard architectures(armv7,armv7s,arm64) 点击这个值,在下拉列表框中选择 Standard architectures(armv7,armv7s) ,然后保存项目,转到 General里面去就可以看到项目的Target选项里面会从4.3到7.0都有. 如果是Xcode 5.1的话步骤为 点击项目名称->

Entity Framework 相关attribute

[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)] //Identifier字段会自动产生guid值,如果Identifier是int类型,那字段就是自增类型. [Table("Retail", Schema = "Chapter2")]public class Retail : Business{ ... } Entity Framework 相关attribute,布布扣,bubuko.com

(一〇四)使用Xcode6创建framework动态静态库

在Xcode6以前,创建framework可以使用iOS-Universal-Framework模板来创建framework,现在苹果已经提供了模板,如下图选择: 使用此模版创建的默认是动态库,方法和上节提到的.a一样,也可以使用lipo来合并真机和模拟器的库. 还有自定义动态库的应用是不被允许上传的. 动态库应该被添加到的位置如下:在工程配置的General之中. 因此应该生成静态库,更改配置的方法如下: framework相比.a,优点是会自动把资源包含到framework内. 版权声明:本

Oracle 表的创建 及相关参数

1. 创建表完整语法 CREATE TABLE [schema.]table (column datatype [, column datatype] - ) [TABLESPACE tablespace] [PCTFREE integer] [PCTUSED integer] [INITRANS integer] [MAXTRANS integer] [STORAGE storage-clause] [LOGGING | NOLOGGING] [CACHE | NOCACHE] ]; 说明:

Xcode创建可复用的代码块

Xcode创建可复用的代码块 在各种程序开发中,编写代码的效率是非常重要的一个问题,各种优秀的编译器也都有相应的插件用于提高程序员的编码速度.在xcode中,可以通过定义代码块的方式将常用的一部分代码进行快捷呼出,首先xcode中为我们定义好了许多代码块,例如: 在使用这些代码模板时,我们只需要将其拖入我们的代码中,或者直接键入快捷键即可,十分的方便,当然,我们也可以将我们自己常用的代码块包装成模板,便于我们复用. 例如,我写如下的代码段: @property(nonatomic,copy)NS

Apple Watch开发(二)--Xcode创建项目及其结构

在上一篇文章中介绍了Apple Watch的特点和app运行模式,那么这篇我们来看下如何利用Xcode创建一个Apple Watch的project. 一. 运行环境 首先我们来用这个Xcode创建Watch app的时候肯定要注意开发环境,Watchkit是在Xcode6.2beta版本加入的,所以我们需要: 1.     电脑系统在Mac OS10.9.4以上: 2.     Xcode在6.2beta版本以上,当然现在Xcode已经到6.3.1了,用最新版就可以了: 二. 创建项目 具备开