這一陣子搞模塊化開發(fā),碰到了好多問題,剛騰出時間總結(jié)、分享一下。
為什么最后敲定選用cocoapods來進行模塊化開發(fā)呢
因為我不會用linux 命令去改xcode的buildSettings,當(dāng)然,如果有會的留言或者私信告訴我,不勝感激……報酬是你出花生我出酒,聚在一起喝兩口 PS:本人不敢喝酒哈~
最好的學(xué)習(xí)cocoapods當(dāng)然是到官網(wǎng)了 https://cocoapods.org/。 從安裝到使用都比較全面,當(dāng)然在安裝或者使用過程中,如果有問題,那就谷歌百度,各種谷歌百度各種的有解決方法。本文通過podspec文件的編寫,講述如何使用cocoapods實現(xiàn)模塊化開發(fā)。
一說到要自己創(chuàng)建pod管理,一谷歌百度就是
pod trunk push NAME.podspec
很多都糾結(jié)在
cd ~/code/Pods/NAME
pod lib lint
這里不用糾結(jié)了,為啥呢?因為你在做項目呢,你肯定不能公開你的東西,項目都是存放在自己git服務(wù)器上了。當(dāng)然以后肯定要 pod trunk push 上去的,因為開源一直都是我力贊的……
創(chuàng)建過程詳見官網(wǎng)Making a CocoaPod。
這里我們根據(jù)資源的存放位置分為三種:
- public server (比如gitHub,誰都能看到)
- private server (自己的git服務(wù)器了,自己和管理員能看見)
- local (存在本地磁盤的一個角落里,自己偷著看)
通過podspec我們來分析具體的實現(xiàn),首先到我們對應(yīng)的模塊文件夾下創(chuàng)建一個podspec,名字呢,我建議跟你的模塊名字一樣,你要不一樣倒也無妨反正。看看我們這個模塊的文件夾目錄結(jié)構(gòu),podspec按照這個結(jié)構(gòu)去寫的,當(dāng)然怎么寫那都無所謂啊,看個人喜好,下面的目錄結(jié)構(gòu)只是用來舉栗子的,下面我舉個栗子:
ZuiyeModule 有這么個模塊,結(jié)構(gòu)如下

各種各樣的文件是吧,盡可能的全乎,在命令行里先進到ZuiyeModule這個目錄下,創(chuàng)建一個podspec
pod spec create ZuiyeModule
該文件夾下就創(chuàng)建了一個這樣的podspec文件

我們打開看一下
open ZuiyeModule.podspec
內(nèi)如如下
#
# Be sure to run `pod spec lint ZuiyeModule.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 = "ZuiyeModule"
s.version = "0.0.1"
s.summary = "A short description of ZuiyeModule."
# 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
DESC
s.homepage = "http://EXAMPLE/ZuiyeModule"
# 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 (example)"
# 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 = { "yuhailong" => "714387953@qq.com" }
# Or just: s.author = "yuhailong"
# s.authors = { "yuhailong" => "714387953@qq.com" }
# s.social_media_url = "http://twitter.com/yuhailong"
# ――― 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 = "5.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 => "http://EXAMPLE/ZuiyeModule.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 = "Classes", "Classes/**/*.{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 = "Resources/*.png"
# 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 "JSONKit", "~> 1.4"
end
我們看一下都需要配置哪些參數(shù),沒加#注釋的都是必要的字段
s.name = "ZuiyeModule"
s.version = "0.0.1"
s.summary = "A short description of ZuiyeModule."
name、version、summary這個比較直觀哈
s.description = <<-DESC
DESC
描述,在DESC中間寫,比如
s.description = <<-DESC
這個是我測試的,這個模塊主要實現(xiàn)自定義功能
DESC
s.homepage = "http://EXAMPLE/ZuiyeModule"
主頁么,沒要求,隨便寫,但也別太隨便了,最好是當(dāng)前模塊在git的主頁(如果你是本地的pod類庫,那這個也沒有用)
s.license = "MIT (example)"
如果你在gitHub上創(chuàng)建項目這個是必選的

s.license = "MIT"
s.author = { "yuhailong" => "714387953@qq.com" }
作者: 嘴爺
# s.platform = :ios, "8.0"
平臺:IOS 最低版本:8.0
# deployment_target或者s.platform不開啟,那在使用的時候會有arc問題(后續(xù)podspec文件中設(shè)置只支持arc)
# 比如__weak不能使用
# When using multiple platforms
# s.ios.deployment_target = "5.0"
# s.osx.deployment_target = "10.7"
# s.watchos.deployment_target = "2.0"
# s.tvos.deployment_target = "9.0"
部署版本
deployment_target或者s.platform不開啟,那在使用的時候會有arc問題(后續(xù)podspec文件中設(shè)置只支持arc) 比如__weak不能使用,
設(shè)置了 s.platform 后,這個可以不用管
s.source = { :git => "http://EXAMPLE/ZuiyeModule.git", :tag => "#{s.version}" }
資源的git 地址,四種寫法,喜歡哪種隨意
# source的寫法可以參照下面的寫法
#pod 'VenderName', :git => 'https://github.com/zuiye/ZuiyeSDK.git', :tag => '0.7.0'
#pod 'VenderName', :git => 'https://github.com/zuiye/ZuiyeSDK.git', :branch => 'develop'
#pod 'VenderName', :git => 'https://github.com/zuiye/ZuiyeSDK.git', :commit => '082f8319af'
# 當(dāng)引用本地的時候這個參數(shù)就沒有用了
s.source = { :git => "local" }
s.source_files = "Classes", "Classes/**/*.{h,m}"
代碼文件,Classes 文件夾,/**/表示文件夾下的所有文件和文件夾, *.{h,m,mm} 表匹配該文件夾下的所有.h .m .mm文件,多個文件路徑用逗號分開
# 所有需要引用的文件都要添加進來 /**/表示所有文件夾 *.{文件后綴}代表所有符合后綴名的文件
s.source_files = "Classes", "Classes/**/*.{h,m,mm}", "Resources/**/*.{h,m,mm}"
# s.resource = "icon.png"
# s.resources = "Resources/*.png"
資源文件,我理解的是除了代碼之外的所有文件.asset .a .framework. .xib .storyboard等等
# png,xib,bundle 等必須當(dāng)資源文件去添加 framework,a 不能引用,否則打包之后體積將包含該整個a文件
s.resource = 'Resources/**/*.{png,xib,bundle,xcassets}'
# s.resources = "Resources/*.png"
當(dāng)然我們在寫代碼的時候也不方便去吧xib跟關(guān)聯(lián)的類分開,所以我們可以把資源文件跟類文件放一起,把 Resources 文件夾換成 Classes 文件夾就好了
s.resource = 'Classes/**/*.{png,xib,bundle,xcassets}'
# s.preserve_paths = "FilesToSave", "MoreFilesToSave"
framework要加preserve_paths 預(yù)加載路徑
# framework要加preserve_paths 預(yù)加載路徑
s.preserve_paths = "Resources/**/*.{framework,a}"
# s.framework = "SomeFramework"
# s.frameworks = "SomeFramework", "AnotherFramework"
# s.library = "iconv"
# s.libraries = "iconv", "xml2"
以上要注意多個framework或者library用逗號分開就行,這個是系統(tǒng)的,如果是三方的framework 或者 library呢
# ――― Linking 相關(guān)參數(shù)說明―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# s.libraries 表示這個pod依賴的 蘋果官方的庫,也就是類似libstdc++.a ,libsqlite.a 等等的a文件;
# s.vendored_libraries 就表示用戶自己的a文件,比如新浪微博SDK的libWeiboSDK.a, 微信libWeChatSDK.a;
# s.frameworks 表示pod依賴的 蘋果的framework, 比如 UIKit,SystemConfiguration等等
# s.vendored_frameworks, 表示pod依賴的自己的framework,比如QQSDK的TencentOpenAPI.framework,JSPatch熱更新JSPatchPlatform.framework;
# .a 或者 libz.tbd 后綴不要,名字里lib開頭的三個字母不要,libz.tbd 應(yīng)寫成 'z'
# ――― Linking 相關(guān)參數(shù)說明 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
針對本模塊的寫法示例
# s.library = 'z'
s.libraries = 'iconv','sqlite3','stdc++','z'
s.vendored_libraries = 'Resources/lib/**/*.{a}'
s.vendored_frameworks = 'Resources/Framework/**/*.{framework}'
# s.requires_arc = true
ARC
#s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SRCROOT)/usr/include/libxml2" }
#s.xcconfig = { 'LIBRARY_SEARCH_PATHS' => '"$(PODS_ROOT)/xxx/xxx"' }
#s.xcconfig = { "FRAMEWORK_SEARCH_PATHS" => "Resources/Framework" }
這個配制想必大家在沒用pod的時候,引入三方的時候,多多少少都要改點
# s.dependency "JSONKit", "~> 1.4"
依賴,可以依賴本地寫法就好比podFile中的寫法,多個依賴,那就多寫幾行
s.dependency "JSONKit", "~> 1.4"
s.dependency 'BaseModel', :path => 'BaseProject/BaseModel'
因為有依賴了,所以AFNetworking、SDWebImage什么的可以不用寫的podFile里了
podFile中的寫法
# ――― PodFile 中的寫法可以如下 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#組件通信 如果提交到spec倉庫,并審核通過
#pod 'CTMediator', '~> 0.0.3'
# 以下所有的spec文件都沒有提交到spec倉庫
#首頁 代碼在git上
#pod 'EHomePage', :git => 'https://github.com/yhl714387953/EHomePage.git'
#首頁使用本地代碼 git上有相關(guān)的代碼 這里用的絕對路徑,不建議,可仿如下用相對路徑
#pod 'EHomePage', :podspec => '~/Desktop/EHomePage/EHomePage.podspec'
#首頁使用本地代碼 代碼只在本地了,文件路徑可以直接簡寫成PodFile所在文件夾之后的路徑
#pod 'BaseModel', :path => 'BaseProject/BaseModel'
# ――― PodFile 中的寫法可以如上 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
我們podspec寫完了,執(zhí)行下
pod update --no-repo-update

我們看看項目里的結(jié)構(gòu)

如果文件夾里少了個某個文件夾,是因為那個文件夾里沒有東西。
新添加的 ZuiyeModel 在 Development Pods 文件夾下了,如果你覺得寫的麻煩,那就按我的文件目錄放置,podspec 文件內(nèi)容都復(fù)制過去然后改個s.name 就行了
s.name = "自己的模塊名字"
現(xiàn)成的大魚在下面了(podspec 內(nèi)容)
# ――― PodFile 中的寫法可以如下 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#組件通信 如果提交到spec倉庫,并審核通過
#pod 'CTMediator', '~> 0.0.3'
# 以下所有的spec文件都沒有提交到spec倉庫
#首頁 代碼在git上
#pod 'EHomePage', :git => 'https://github.com/yhl714387953/EHomePage.git'
#首頁使用本地代碼 git上有相關(guān)的代碼 這里用的絕對路徑,不建議,可仿如下用相對路徑
#pod 'EHomePage', :podspec => '~/Desktop/EHomePage/EHomePage.podspec'
#首頁使用本地代碼 代碼只在本地了,文件路徑可以直接簡寫成PodFile所在文件夾之后的路徑
#pod 'BaseModel', :path => 'BaseProject/BaseModel'
# ――― PodFile 中的寫法可以如上 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Be sure to run `pod spec lint JSPatchModule.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 = "ZuiyeModule"
s.version = "1.0.0"
s.summary = "測試資源文件,png、 xib、 bundle、 a、 framework"
# 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
測試資源文件
DESC
s.homepage = "www.zuiye.com"
# 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 = { "yuhailong" => "714387953@qq.com" }
# Or just: s.author = "yuhailong"
# s.authors = { "yuhailong" => "714387953@qq.com" }
# s.social_media_url = "http://twitter.com/yuhailong"
# ――― 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, "8.0"
# When using multiple platforms
# s.ios.deployment_target = "5.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.
#
# source的寫法可以參照下面的寫法
#pod 'VenderName', :git => 'https://github.com/zuiye/ZuiyeSDK.git', :tag => '0.7.0'
#pod 'VenderName', :git => 'https://github.com/zuiye/ZuiyeSDK.git', :branch => 'develop'
#pod 'VenderName', :git => 'https://github.com/zuiye/ZuiyeSDK.git', :commit => '082f8319af'
# 當(dāng)引用本地的時候這個參數(shù)就沒有用了
s.source = { :git => "local" }
# ――― 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 = "Classes", "Classes/**/*.{h,m,mm}", "Resources/**/*.{h,m,mm}"
#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 ="Classes/View/JSTableView.xib"
#s.resource = ['Classes/**/*.png','Classes/View/*.xib']
# png,xib,bundle 等必須當(dāng)資源文件去添加 framework,a 不能引用,否則打包之后體積將包含該整個a文件
s.resource = 'Resources/**/*.{png,xib,bundle,xcassets}'
# s.resources = "Resources/*.png"
# framework 要加preserve_paths 預(yù)加載路徑
s.preserve_paths = "Resources/**/*.{framework,a}"
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Link your library with frameworks, or libraries. Libraries do not include
# the lib prefix of their name.
#
#s.framework = 'JavaScriptCore'
s.frameworks = 'SystemConfiguration','CoreGraphics','CoreTelephony','Security','CoreLocation','JavaScriptCore'
# s.library = 'z'
s.libraries = 'iconv','sqlite3','stdc++','z'
s.vendored_libraries = 'Resources/lib/**/*.{a}'
s.vendored_frameworks = 'Resources/Framework/**/*.{framework}'
# ――― Linking 相關(guān)參數(shù)說明―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# s.libraries 表示這個pod依賴的 蘋果官方的庫,也就是類似libstdc++.a ,libsqlite.a 等等的a文件;
# s.vendored_libraries 就表示用戶自己的a文件,比如新浪微博SDK的libWeiboSDK.a ;
# s.frameworks 表示pod依賴的 蘋果的framework, 比如 UIKit,SystemConfiguration等等
# s.vendored_frameworks, 表示pod依賴的自己的framework,比如QQSDK的TencentOpenAPI.framework;
# .a 或者 libz.tbd 后綴不要,名字里lib開頭的三個字母不要,libz.tbd 應(yīng)寫成 'z'
# ――― Linking 相關(guān)參數(shù)說明 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# ――― 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" => "$(SRCROOT)/usr/include/libxml2" }
#s.xcconfig = { 'LIBRARY_SEARCH_PATHS' => '"$(PODS_ROOT)/xxx/xxx"' }
#s.xcconfig = { "FRAMEWORK_SEARCH_PATHS" => "Resources/Framework" }
# s.dependency "JSONKit", "~> 1.4"
end
感謝您閱讀完畢,如有疑問,歡迎添加QQ:714387953(蝸牛上高速)。
github:https://github.com/yhl714387953/SpecModule
如果有錯誤,歡迎指正,一起切磋,共同進步
如果喜歡可以Follow、Star、Fork,都是給我最大的鼓勵