需求原因
主項目隨著業(yè)務的增多,體積和代碼量越來越大,代碼耦合性高,也不利于bug的定位,新同事也需要花很長時間消化。故將項目組件化提上日程——主項目由主項目代碼+公共組件庫+業(yè)務需求組件等構成,目錄如下:
//主項目
—— XQMainProject
/*主項目無法組件化的代碼*/
└── XQMainProjectCode
/*公共組件*/
//通用的UI控件庫
└── XQ_UIKit
//公共的Category,工具類,宏定義等
└── XQ_UIFoundation
...
/*業(yè)務組件*/
//新聞模塊
└── XQ_News
//商城模塊
└── XQ_Store
//視頻模塊
└── XQ_Video
...
本文不是在于記錄如何搭建、使用、發(fā)布私有庫,對此有興趣可以看這里。本文是對比傳統(tǒng)構建私有庫方法創(chuàng)建的項目目錄,自定義新的,更加方便的項目架構目錄。
分析 pod lib create 創(chuàng)建的私有庫
在終端中執(zhí)行:
pod lib create <LibName>
如
pod lib create XQComponentTmp
然后按提示進行配置,最后會生成如下圖所示的目錄結構:

右上圖可知,創(chuàng)建后的項目目錄整理如下:
—— XQComponentTmp
/*Pods項目的副本*/
└── _Pods.xcodeproj
/*私有庫的演示demo項目*/
└── Example
/*demo項目代碼*/
└── XQComponentTmp
/*demo項目*/
└── XQComponentTmp.xcodeproj
/*xcworkspace,管理demo項目和Pods項目*/
└── XQComponentTmp.xcworkspace
/*Podfile文件*/
└── Podfile
/*Pods相關的文件*/
└── Pods
...
/*私有庫*/
└── XQComponentTmp
/*私有庫資源文件*/
└── Assets
/*私有庫所有代碼文件*/
└── Classes
/*私有庫的podspec文件*/
└── XQComponentTmp.podspec
/*Git管理相關文件*/
└──.git
...
所以,這種方式創(chuàng)建的工程目錄這么幾點不太便捷:
1、git和私有庫代碼在一級目錄,pods在二級目錄,若私有庫發(fā)生更改,則提交代碼到遠程倉庫需切換到一級目錄,演示demo項目更新私有庫需回到二級目錄。更改頻繁,需頻繁切換,容易造成錯誤。
2、觀察workspace目錄結構,Pods引入了私有庫XQComponentTmp,且代碼嵌套在三級目錄,不方便查看管理。

由上圖也可感受到,整個項目目錄并不怎么清爽,故構思自定義私有庫的目錄結構,使得git管理和pod管理在一個目錄結構下,且整個代碼架構清新。
自定義私有庫的搭建目錄
1、自定義的私有庫目錄結構:
—— XQComponentTmp
/*私有庫的podspec文件*/
└── XQComponentTmp.podspec
/*私有庫項目*/
└── XQComponentTmp.xcodeproj
/*私有庫的所有代碼資源文件*/
└── XQComponentTmp
/*私有庫資源文件*/
└── Assets
/*私有庫所有代碼文件*/
└── Classes
/*演示demo*/
└── XQComponentTmpDemo
/*demo項目*/
└── XQComponentTmpDemo.xcodeproj
/*demo項目的所有代碼資源文件*/
└── XQComponentTmpDemo
/*workspace文件*/
└──XQComponentTmp.xcworkspace
/*Podfile文件*/
└── Podfile
/*Pods相關的文件*/
└── Pods
/*Git管理相關文件*/
└──.git
...
- 將
Pods和Git放在一級目錄,方便管理操作。 - 將私有庫文件夾還是放在一級目錄,其代碼和資源通過項目來管理,初步構思是利用靜態(tài)庫。
workspace同時管理XQComponentTmpDemo.xcodeproj、Pods.xcodeproj、XQComponentTmp.xcodeproj。如此就不用在workspace中的Pods下去編輯私有庫文件。
2、實踐
2.1、創(chuàng)建私有庫
-
Xcode中創(chuàng)建新的project,選擇 靜態(tài)庫模版Cocoa Touch Framework,命名為XQComponentTmp。 - 然后在
XQComponentTmp/XQComponentTmp目錄下創(chuàng)建兩個文件夾Classes、Assets,用于存放私有庫文件和資源,引入到項目中。 - 創(chuàng)建podspec文件:
pod spec create <LibName> //此處LibName為XQComponentTmp
編輯配置:
#
# Be sure to run `pod lib lint XQComponentTmp.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'XQComponentTmp'
s.version = '0.1.0'
s.summary = 'XQ自定義組件模版'
# 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
XQ自定義組件模版,用于公共、業(yè)務組件的構造。
DESC
s.homepage = 'https://github.com/xq0216/XQComponentTmp'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'xq' => 'xxx@gmail.com' }
s.source = { :git => 'git@github.com:xq0216/XQComponentTmp.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'XQComponentTmp/Classes/**/*'
s.resource_bundle = {
'XQComponentTmp_Bundle' => ['XQComponentTmp/Assets/*.xcassets']
}
s.public_header_files = 'XQComponentTmp/Classes/**/*.h'
#依賴的系統(tǒng)庫
s.frameworks = 'UIKit', 'Foundation', 'CoreGraphics'
#依賴的第三方庫
#s.dependency 'BeeHive', '1.6.0'
#s.dependency 'JLRoutes', '2.1'
#s.dependency 'JSONModel', '~> 1.7.0'
#s.dependency 'Masonry', '~> 1.1.0'
end
那么此時私有庫項目就初步創(chuàng)建完成,可以在Classes目錄下簡單創(chuàng)建私有庫文件:

2.2、創(chuàng)建Demo演示項目
demo項目用于演示如何使用私有庫,方便主項目快速集成使用。
- 在
XQComponentTmp/目錄下創(chuàng)建一個新的項目應用XQComponentTmpDemo,模版可直接選擇Single View App。 - 然后在同一目錄創(chuàng)建和編輯Podfile
/*創(chuàng)建*/
touch Podfile
/*編輯*/
vim Podfile
編輯后如下:
#use_frameworks!
platform :ios, '8.0'
#指定源
source 'https://github.com/CocoaPods/Specs.git'
# 辨識是哪個workspace,沒有則創(chuàng)建名為XQComponentTmp的workspace
workspace 'XQComponentTmp'
# 辨識是哪個target
target 'XQComponentTmpDemo' do
# 辨識是哪個項目
project 'XQComponentTmpDemo/XQComponentTmpDemo.xcodeproj'
# 引入私有庫(同級路徑)
pod 'XQComponentTmp', :path => './'
end
################## Pods Script ###################
#配置Pods工程預編譯宏
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name.include?('Debug')
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = 0
end
end
end
end
- 然后在同一目錄執(zhí)行
pod安裝:
pod install
此時demo項目已經完成了私有庫的引入,完整文件目錄如下所示:

- 打開
workspace,此時workspace管理了XQComponentTmpDemo.xcodeproj、Pods.xcodeproj兩個項目,直接將XQComponentTmp.xcodeproj拖入到workspace中,即可完成workspace管理三個項目。
完整的項目目錄
由此,完成了自定義私有庫目錄的構造。
1)編輯私有庫,可直接忽略Pods部分,在XQComponentTmp.xcodeproj目錄下進行編輯,結構更清晰。
2)若私有庫中增刪了文件,需要執(zhí)行pod install后,demo項目引入的私有庫才能生效,若僅僅是編輯了某文件,如增加了某個方法,demo項目直接生效。
2.3、測試私有庫
- 在私有庫的Classes中創(chuàng)建文件:XQTestView.h/m文件
- (id)init{
self = [super init];
if (self) {
self.backgroundColor = [UIColor redColor];
}
return self;
}
- 新增了文件,故執(zhí)行
pod install,使得demo項目引入私有庫最新代碼,編輯demo的ViewController.m文件:
- (void)viewDidLoad {
[super viewDidLoad];
//test component
XQTestView *testView = [[XQTestView alloc]init];
testView.frame = CGRectMake(0, 0, 100, 100);
testView.center = self.view.center;
[self.view addSubview:testView];
}
-
選擇XQComponentTmpDemo工程,編譯運行:
測試結果
3、補充
3.1、私有庫依賴其他庫
1)若私有庫本身有依賴其他庫(第三方庫、私有庫等),如G7_ResourceManage.podspec文件中:
#依賴的第三方庫
s.dependency 'JSONModel', '~> 1.7.0'
2)這個私有庫也需要pod管理依賴的第三方庫,所以podfile中添加如下:
target 'XQComponentTmp' do
# 辨識是哪個項目
project 'XQComponentTmp.xcodeproj'
pod 'JSONModel', '~> 1.7.0'
end
3)執(zhí)行pod install,這樣私有庫即能成功和第三方庫進行管理。
4)測試:
在XQComponentTmp/Class目錄下,添加繼承于JSONModel的子類XQTestModel,然后編譯XQComponentTmp:

若編譯成功,說明
XQTestModel.h中成功#import "JSONModel.h",即成功關聯(lián)上第三方庫。私有庫引用第三方庫成功!
3.2、添加代碼格式化
clang-format 是真正實現(xiàn)代碼規(guī)范的執(zhí)行文件(網上找的,可以配置代碼規(guī)范規(guī)則,之后抽空研究下),利用shell腳本,在編譯時,動態(tài)執(zhí)行clang-format,來實現(xiàn)進行代碼格式化。shell腳本formatCodeStyle.sh如下所示 :
#!/bin/sh
clang_format=$SRCROOT/bin/clang-format
run_clangformat() {
local filename="${1}"
cd $SRCROOT
if [ ! -f "$filename" ]; then
return
fi
FILE_ALIAS='file'
if [[ "${filename##*.}" == "m" || "${filename##*.}" == "h" || "${filename##*.}" == "mm" || "${filename##*.}" == "hpp" || "${filename##*.}" == "cpp" || "${filename##*.}" == "cc" ]]; then
echo "$SRCROOT/$filename"
echo "存在"
$clang_format -i -style=$FILE_ALIAS "$SRCROOT/$filename"
fi
}
git diff --name-only | grep "XQComponentTmp/" | while read filename; do run_clangformat "${filename}"; done
shell腳本配置:選中需要添加代碼規(guī)范的文件所屬的Target,Build Phases 下 New Run Script Phase:

echo "開始格式化"
"${SRCROOT}/scripts/formatCodeStyle.sh"
這樣,每次編譯,該工程的所有文件代碼,就自動進行了格式化。(可以用if-else進行測試)

