当一种编程语言应用于企业级开发,为了提高代码的复用率,伟大的程序员们将一些可以复用的公共的代码封装起来,形成第三方库,供其他人使用,当这些第三方库数量及其庞大的时候,如何有效的管理和分发这些库就成了一个问题,在iOS开发中Cocoapods由此诞生
给自己的库添加Cocoapods支持
1、安装Cocoapods(假设已经安装了Cocoapods)
假设你已经安装了Cocoapods,如果还没有安装,请看这篇文章Cocoapods 安装及使用
2、准备一个需要添加Cocoapods支持的库项目
2.1在github上已经有一个项目
我这边有一个项目ViewImageInWebView 你如果已经有一个项目了,和我一样把他clone到本地在第三步要使用
2.2 在github上新建一个项目
要是没有项目,在github上直接新建一个项目,然后clone到本地
3、添加Cocoapods支持
3.1 注册trunk
CocoaPods 0.33中加入了 Trunk 服务,使用 Trunk 服务可以方便的发布自己的Pod。虽然一开始使用 GitHub Pull Requests 来整理所有公共 pods 效果很好。但是,随着 Pod 数量的增加,这个工作对于 spec 维护人员 Keith Smiley 来说变得十分繁杂。甚至一些没有通过 $ pod lint 的 spec 也被提交上来,造成 repo 无法 build。CocoaPods Trunk 服务的引入,解决了很多类似的问题。每次使用 Trunk 服务发布 Pod 时都会通过 $ pod lint 验证 .podspec 是否有效。要想使用 Trunk 服务,首先需要使用如下命令注册自己的电脑。这很简单,只要你指明你的邮箱地址(spec文件中的)和名称即可。CocoaPods 会给你填写的邮箱发送验证邮件,点击邮件中的链接就可通过验证。
//向trunk注册 格式为:pod trunk register 邮箱 用户名 --verbose为显示详细信息(可选)
pod trunk register fdai_itlogic@163.com 'SvenDai' --verbose
//查看注册信息
pod trunk me
在命令行键入以上命令后,其会向你的邮箱发送一条验证邮件,打开连接验证一下就行。
3.2 编写 xxx.podspec 文件
以上步骤之后,接下来要编写相应的xxx.podspec 文件,其中,xxx一般写自己的项目库的名称例如:ViewImageViewInWebView.podspec (据说也可以随便写,我没有验证过)。
1)首先创建ViewImageViewInWebView.podspec 文件
注意:需要切换到你需要添加Cocoapods支持的库的根目录下进行文件的创建(不知道啥是根目录的打开我的上面的项目的文件夹看一下)
//执行以下命令后,你会发现你的项目根目录文件夹下多出一个ViewImageViewInWebView.podspec 文件
pod spec create ViewImageInWebView
当然你也可以使用vim创建,只是没有默认cocoapods提供的模板文本而已
2)编辑ViewImageViewInWebView.podspec 文件
推荐使用vim以免后面验证的时候因为字符的原因出现错误。vim打开文件后出现如下很长的内容。
#
# Be sure to run `pod spec lint ViewImageInWebView.podspec' to ensure this is a
# valid spec and to remove all comments including this before submitting the spec.
#
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#
Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# These will help people to find your library, and whilst it
# can feel like a chore to fill in it's definitely to your advantage. The
# summary should be tweet-length, and the description more in depth.
#
s.name = "ViewImageInWebView"
s.version = "0.0.4"
s.summary = "A view allow you browse big image in webView"
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
browse big image in webView, pod lib lint say I need lang lang land description
DESC
s.homepage = "https://github.com/SvenDai/ViewImageInWebView"
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Licensing your code is important. See http://choosealicense.com for more info.
# CocoaPods will detect a license file if there is a named LICENSE*
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
#
s.license = "MIT"
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the authors of the library, with email addresses. Email addresses
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
# accepts just a name if you'd rather not provide an email address.
#
# Specify a social_media_url where others can refer to, for example a twitter
# profile URL.
#
s.author = { "fdai" => "fdai_itlogic@163.com" }
# Or just: s.author = "fdai"
# s.authors = { "fdai" => "fdai_itlogic@163.com" }
# s.social_media_url = "http://twitter.com/fdai"
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If this Pod runs only on iOS or OS X, then specify the platform and
# the deployment target. You can optionally include the target after the platform.
#
# s.platform = :ios
# s.platform = :ios, "5.0"
# When using multiple platforms
s.ios.deployment_target = "7.0"
# s.osx.deployment_target = "10.7"
# s.watchos.deployment_target = "2.0"
# s.tvos.deployment_target = "9.0"
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the location from where the source should be retrieved.
# Supports git, hg, bzr, svn and HTTP.
#
s.source = { :git => "https://github.com/SvenDai/ViewImageInWebView.git", :tag => s.version }
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any swift, h, m, mm, c & cpp files.
# For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public.
#
s.source_files = "ViewImageInWebView/DFBrowseImageView/**/*.{h,m}"
#s.exclude_files = "Classes/Exclude"
# s.public_header_files = "Classes/**/*.h"
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# A list of resources included with the Pod. These are copied into the
# target bundle with a build phase script. Anything else will be cleaned.
# You can preserve files from being cleaned, please don't preserve
# non-essential files like tests, examples and documentation.
#
# s.resource = "icon.png"
s.resources = "ViewImageInWebView/Assets.xcassets"
# s.preserve_paths = "FilesToSave", "MoreFilesToSave"
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Link your library with frameworks, or libraries. Libraries do not include
# the lib prefix of their name.
#
# s.framework = "SomeFramework"
# s.frameworks = "SomeFramework", "AnotherFramework"
# s.library = "iconv"
# s.libraries = "iconv", "xml2"
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If your library depends on compiler flags you can set them in the xcconfig hash
# where they will only apply to your library. If you depend on other Podspecs
# you can include multiple dependencies to ensure it works.
s.requires_arc = true
# s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
s.dependency 'Masonry'
s.dependency 'SDWebImage' , '~>3.8.1'
end
这是官方提供的模板,每个部分都有简短的说明,要详细了解可以看官方文档的说明,(个人建议从头到尾撸一遍,嫌弃他长的话,直接全部删除,然后找个优秀的第三方库模仿着写也是个不错的办法)下面针对我的这个项目做详细说明
Pod::Spec.new do |s|
#项目名称,pod search 时用的名称
s.name = "ViewImageInWebView"
#库的版本号,提交到github时给 commit打的tag的标志(后面有说明)
s.version = "0.0.4"
#项目描述
s.summary = "A view allow you browse big image in webView"
#项目主页
s.homepage = "https://github.com/SvenDai/ViewImageInWebView"
#项目的license
s.license = "MIT"
#作者
s.author = { "fdai" => "fdai_itlogic@163.com" }
#系统版本要求
s.ios.deployment_target = "7.0"
#库文件的位置,和对应的版本号(对应的版本号下的代码)
s.source = { :git => "https://github.com/SvenDai/ViewImageInWebView.git", :tag => s.version }
#需要的代码文件(A/**/*.{h.m} 表示A文件夹及其子文件夹下的所有.h.m文件)
s.source_files = "ViewImageInWebView/DFBrowseImageView/**/*.{h,m}"
#需要的资源
s.resources = "ViewImageInWebView/Assets.xcassets"
#arc模式
s.requires_arc = true
#这个库依赖的其他库
s.dependency 'Masonry'
s.dependency 'SDWebImage' , '~>3.8.1'
end
你的项目可能还需要添加依赖库和framework等按需要添加
ViewImageInWebView.podspec文件最后要提交到cocoapods库中,在我理解,这个文件的作用就是,当其他人通过cocoapods使用你的库的时候,通过这个配置文件,找到你的库的位置,将库下载下来,并根据这配置文件的描述信息去配置你的库所需要的运行环境。
3.3 验证 xxx.podspec 文件
编辑好保存以后,输入以下命令进行验证,这部的验证会验证文件编写是否有语法错误
pod lib lint ViewImageInWebView.podspec
验证通过会出现如下界面:要是出错了请拉到文章最后
3.4 提交代码和xxx.spec 文件
将验证通过的xxx.spec 文件以及提交到github上
git add .
git commit 'add cocoapods support'
git push
3.5 给上次的提交打tag 提交 tag
注意这步和3.4的区别,3.4只是做了一次提交并没有给这次提交打tag,而我们在xxx.spec文件中有这样一个配置‘
s.source = { :git => "https://github.com/SvenDai/ViewImageInWebView.git", :tag => s.version }
就是说,我们拉库的代码是按照对应的tag拉下来的,所以我们要打上tag,这样它才能找到对应的代码(我就是因为commit和tag没有对应起来,最后提交没有验证通过)
git tag 0.0.4
git tag
git push origin 0.0.4
注意: 这里的tag要和 xxx.spec中的s.version 对应起来
3.6 提交xxx.spec 文件到Cocoapods
pod trunk push ViewImageInWebView.podspec
幸运的话,会出现以下界面,恭喜你成功了
其实在这一步也会进行一次验证
验证 .podspec 会先测试本地 .podspec 文件是否存在语法错误。测试成功再根据 .podspec 文件找到远端仓库对应的版本克隆到本地并进行配置。最后测试文件是否能够编译成功。
如果失败了,请拉倒文章最后(我就是失败了的)
3.7 查找添加了cocoapods支持的库
如果你和我一样以为3.6提交成功了你兴冲冲的输入一下命令
pod search 'ViewImageInWebView'
出现如下界面:(顿时萌币,为啥找不到呢)
这时你再输入以下命令试试
rm ~/Library/Caches/CocoaPods/search_index.json
pod search 'ViewImageInWebView'
成功!!!
这时因为,当你第一次查找的时候,你的搜索索引是旧的索引,而你的库是刚刚提交上去的,rm ~/Library/Caches/CocoaPods/search_index.json是删除旧的查找索引,pod search 'ViewImageInWebView' 时会去拉新的索引(新建索引是耗时操作,需要一点时间)
版本升级
当需要更新 Pod 版本的时候,修改 .podspec 中的 s.version 为更高的版本号,并修改 s.source 中对应的 Git 版本。提交到Git,并打上对应tag。然后再次执行pod trunk push xxx.podspec将新的 .podspec 发布到 CocoaPods。更新完成!
为了更新更加方便,版本控制更加清晰,s.source 建议采用如下写法:
s.source = { :git => "https://github.com/SvenDai/ViewImageInWebView.git", :tag => s.version }
这样写将 Git 的版本与 CocoaPods 的版本进行了绑定。每次提交后再给本次提交打上 tag 就完成了更新。而且在 Git 中就可以清晰的看到哪次提交对应的哪个 CocoaPods 版本。如果与 commit 绑定,则要通过两次提交才能完成更新,第一次先提交修改代码,第二次将上一次 commit id 更新到 s.source 然后再次提交。如果直接与固定 tag 绑定,则每次还都要修改 s.source。如果你的 Pod 是私有库,那么 s.source 其实是无用的。因为在 Podfile 中已经指明了地址和版本(如下)。这时 s.source 可以随便填写,但最好还是按照上述规则以便以后发布。
pod 'ViewImageInWebView', :git => 'https://github.com/SvenDai/ViewImageInWebView.git', :tag => 1.0.0
出错处理
1、我在3.3的验证步骤验证了4次才通过,除了基本的语法错误之外主要有两个错误如下:
error: include of non-modular header inside framework module 'ViewImageInWebView.DFBrowseImageView' [-Werror,-Wnon-modular-include-in-framework-module]
解决:自建的私有库项目中有第三方依赖库,且在.h文件中做了#import引入,改成在.m文件中#import引用即可。
[!] The validator for Swift projects uses Swift 3.0 by default, if you are using a different version of swift you can use a
.swift-version
file to set the version for your Pod. For example to use Swift 2.3, run:
echo "2.3" > .swift-version
.
解决:echo "2.3" > .swift-version
2、我在3.6提交xxx.spec文件到cocoapods的时候也出现了错误,错误和上面一样,我就纳闷了,明明验证可以通过,但是提交还出错,后来,我发现我在解决3.3验证步骤的问题时修改了代码进行了提交之后,但是忘记改xxx.spec中的s.version版本号,按照我在3.6所说的,提交xxx.spec文件到cocoapods的时候也会进行验证,这样验证时拉下来的代码并不是我修改之后的代码(tag=0.04),而是之前的代码(tag=0.01)。找到问题之后,修改,s.verison 提交之后打个tag提交就好了。
参考文档
[干货最新]将自己库添加Cocoapods支持
CocoaPods建立自己的Podspec(三)
github中创建自己的cocoapod私有库_异常问题解决