iOS模块化管理之CocoaPods实战

Posted QiShare

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS模块化管理之CocoaPods实战相关的知识,希望对你有一定的参考价值。

环境准备

更新gem源,如果系统中没有安装gem,请先安装gem环境

$ sudo gem update --system Latest version already installed. Done.

CocoaPods依赖ruby环境,在项目开始前先查看一下本地ruby环境,一般Mac电脑都自带了ruby环境。

$ gem sources -l*** CURRENT SOURCES ***https://rubygems.org/

由于ruby官方源国内被墙,需要修改ruby源。

$ gem sources --remove https://rubygems.org/$ gem sources --add https://gems.ruby-china.com/

查看ruby镜像是否已经切换

$ gem sources -l *** CURRENT SOURCES ***
https://gems.ruby-china.com/

查看本地CocoaPods版本

$ pod --version 1.10.1

如果没有安装CocoaPods,先安装CocoaPods

$ sudo gem install -n /usr/local/bin cocoapods

再次查看CocoaPods版本

$ pod --version 1.10.1

工具准备

工欲善其事必先利其器!

私有仓库准备

创建远程私有仓库。由于示例中仓库名称已经存在,Gitee会有相应的错误提示,但不影响继续往下进行。

将远程仓库添加至本地pod repo中

$ pod repo add ishadoo-specs https://gitee.com/ishadoo/Specs.git

查看本地仓库

$ pod repo list 
ishadoo-specs- Type: git (master)- URL: https://gitee.com/ishadoo/Specs.git- Path: /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs
master- Type: git (master)- URL: https://github.com/CocoaPods/Specs.git- Path: /Users/wangchuanhai/.cocoapods/repos/master
trunk- Type: CDN- URL: https://cdn.cocoapods.org/- Path: /Users/wangchuanhai/.cocoapods/repos/trunk

CHModuleConfig工具

初始化项目,将ios工程与远程git仓库进行关联。

Config脚本:

  • 做了3件事:

    • 初始本地iOS项目,添加podspec文件。
    • 将初始化后的项目与远程私有仓库进行关联。
    • 添加私有库上传脚本。
#!/bin/bash
Cyan='\033[0;36m'Default='\033[0;m'
projectName=""httpsRepo=""sshRepo=""homePage=""confirmed="n"
getProjectName() { read -p "Enter Project Name: " projectName if test -z "$projectName"; then getProjectName fi}
getHTTPSRepo() { read -p "Enter HTTPS Repo URL: " httpsRepo if test -z "$httpsRepo"; then getHTTPSRepo fi}
getSSHRepo() { read -p "Enter SSH Repo URL: " sshRepo if test -z "$sshRepo"; then getSSHRepo fi}
getHomePage() { read -p "Enter Home Page URL: " homePage if test -z "$homePage"; then getHomePage fi}
getInfomation() { getProjectName getHTTPSRepo getSSHRepo getHomePage
echo -e "\n${Default}================================================" echo -e " Project Name : ${Cyan}${projectName}${Default}" echo -e " HTTPS Repo : ${Cyan}${httpsRepo}${Default}" echo -e " SSH Repo : ${Cyan}${sshRepo}${Default}" echo -e " Home Page URL : ${Cyan}${homePage}${Default}" echo -e "================================================\n"}
echo -e "\n"while [ "$confirmed" != "y" -a "$confirmed" != "Y" ]do if [ "$confirmed" == "n" -o "$confirmed" == "N" ]; then getInfomation fi read -p "confirm? (y/n):" confirmeddone
mkdir -p "../${projectName}/${projectName}"
licenseFilePath="../${projectName}/FILE_LICENSE"gitignoreFilePath="../${projectName}/.gitignore"specFilePath="../${projectName}/${projectName}.podspec"readmeFilePath="../${projectName}/readme.md"uploadFilePath="../${projectName}/upload.sh"podfilePath="../${projectName}/Podfile"
echo "copy to $licenseFilePath"cp -f ./templates/FILE_LICENSE "$licenseFilePath"echo "copy to $gitignoreFilePath"cp -f ./templates/gitignore "$gitignoreFilePath"echo "copy to $specFilePath"cp -f ./templates/pod.podspec "$specFilePath"echo "copy to $readmeFilePath"cp -f ./templates/readme.md "$readmeFilePath"echo "copy to $uploadFilePath"cp -f ./templates/upload.sh "$uploadFilePath"echo "copy to $podfilePath"cp -f ./templates/Podfile "$podfilePath"
echo "editing..."sed -i "" "s%__ProjectName__%${projectName}%g" "$gitignoreFilePath"sed -i "" "s%__ProjectName__%${projectName}%g" "$readmeFilePath"sed -i "" "s%__ProjectName__%${projectName}%g" "$uploadFilePath"sed -i "" "s%__ProjectName__%${projectName}%g" "$podfilePath"
sed -i "" "s%__ProjectName__%${projectName}%g" "$specFilePath"sed -i "" "s%__HomePage__%${homePage}%g" "$specFilePath"sed -i "" "s%__HTTPSRepo__%${httpsRepo}%g" "$specFilePath"echo "edit finished"
echo "cleaning..."cd ../$projectNamegit initgit remote add origin $httpsRepo &> /dev/nullgit rm -rf --cached ./Pods/ &> /dev/nullgit rm --cached Podfile.lock &> /dev/nullgit rm --cached .DS_Store &> /dev/nullgit rm -rf --cached $projectName.xcworkspace/ &> /dev/nullgit rm -rf --cached $projectName.xcodeproj/xcuserdata/`whoami`.xcuserdatad/xcschemes/$projectName.xcscheme &> /dev/nullgit rm -rf --cached $projectName.xcodeproj/project.xcworkspace/xcuserdata/ &> /dev/nullgit add . &> /dev/nullgit commit -m "first commit" &> /dev/nullgit push -u origin master &> /dev/nullecho "clean finished"say "finished"echo "finished"

templates

提供初始化上传到CocoaPods仓库模块工程的配置文件模板。

该模板提供了最基础的配置信息。

  • pod.podspec模板

    初始化私有库模块的podspec文件,为后续模块上传到私有仓库初始化基本配置。

    Pod::Spec.new do |s|
    s.name = "__ProjectName__" s.version = "1.0.0" s.summary = "__ProjectName__." s.description = <<-DESC this is __ProjectName__ DESC s.homepage = "__HomePage__" s.license = { :type => "MIT", :file => "FILE_LICENSE" } s.author = { "王传海" => "ishadoo@163.com" } s.platform = :ios, "10.0" s.source = { :git => "__HTTPSRepo__", :tag => s.version } s.source_files = "__ProjectName__/__ProjectName__/**/*.{h,m}" s.requires_arc = true end
  • Podfile模板

    初始项目的Podfile文件

    # Uncomment this line to define a global platform for your projectplatform :ios, '10.0'
    source 'https://gitee.com/ishadoo/Specs.git'source 'https://github.com/CocoaPods/Specs.git'
    target '__ProjectName__' do
    end
  • upload脚本模板

    pod repo push ishadoo-specs __ProjectName__.podspec --verbose --allow-warnings --use-libraries --sources='https://gitee.com/ishadoo/Specs.git,https://github.com/CocoaPods/Specs.git'

项目实战

由于公司git仓库的隐私性以及安全性方面的考虑,本教程以gitee仓库为例,手摸手教大家如何从零搭建一个iOS模块化架构。

准备ModuleConfig

我的项目路径是:~/code/private/CHShare.

$ cd ~/code/private/CHShare$ git clone https://gitee.com/ishadoo/CHModuleConfig.git

创建远程项目地址

远程仓库根据自己的项目环境去选择,教程中我用的是gitee.

iOS模块化管理之CocoaPods实战

创建Xcode本地工程

工程名要与远端工程名称相同,创建时直接复制远端工程名即可,且路径与ModuleConfig平级

iOS模块化管理之CocoaPods实战

此时项目目录结构中多了我们刚创建的CHShareThird工程

iOS模块化管理之CocoaPods实战

利用CHModuleConfig初始化工程并上传到远程仓库

这一步的主要任务是,将本地工程初始化为由CocoaPods管理的工程。

同时将该项目同步到git远程仓库。

终端下cd到CHModuleConfig根目录,执行初始化配置脚本 config.sh。

~ » cd /Users/wangchuanhai/code/private/CHShare/CHModuleConfig ---------------------------------------------------------------------------------------------------------------------------------~/code/private/CHShare/CHModuleConfig(master*) » ll total 32-rw-r--r-- 1 wangchuanhai staff 1.0K 3 7 14:24 LICENSE-rw-r--r-- 1 wangchuanhai staff 839B 3 7 14:24 README.en.md-rw-r--r-- 1 wangchuanhai staff 928B 3 7 14:24 README.md-rwxr-xr-x 1 wangchuanhai staff 3.2K 3 7 14:04 config.shdrwxr-xr-x 6 wangchuanhai staff 192B 3 7 14:06 templates---------------------------------------------------------------------------------------------------------------------------------~/code/private/CHShare/CHModuleConfig(master*) » ./config.sh 

Enter Project Name: CHShareThirdEnter HTTPS Repo URL: https://gitee.com/ishadoo/CHShareThird.gitEnter SSH Repo URL: git@gitee.com:ishadoo/CHShareThird.gitEnter Home Page URL: https://gitee.com/ishadoo/CHShareThird
================================================ Project Name : CHShareThird HTTPS Repo : https://gitee.com/ishadoo/CHShareThird.git SSH Repo : git@gitee.com:ishadoo/CHShareThird.git Home Page URL : https://gitee.com/ishadoo/CHShareThird================================================
confirm? (y/n):ycopy to ../CHShareThird/FILE_LICENSEcp: ./templates/FILE_LICENSE: No such file or directorycopy to ../CHShareThird/.gitignorecp: ./templates/gitignore: No such file or directorycopy to ../CHShareThird/CHShareThird.podspeccopy to ../CHShareThird/readme.mdcp: ./templates/readme.md: No such file or directorycopy to ../CHShareThird/upload.shcopy to ../CHShareThird/Podfileediting...sed: ../CHShareThird/.gitignore: No such file or directorysed: ../CHShareThird/readme.md: No such file or directoryedit finishedcleaning...Initialized empty Git repository in /Users/wangchuanhai/code/private/CHShare/CHShareThird/.git/clean finishedfinished

切换到CHShareThird工程,发现多了三个文件

  • CHShareThird.podspec
  • Podfile
  • upload.sh
~/code/private/CHShare/CHModuleConfig(master*) » cd .. ---------------------------------------------------------------------------------------------------------------------------------~/code/private/CHShare » ll total 0drwxr-xr-x 9 wangchuanhai staff 288B 3 7 14:25 CHModuleConfigdrwxr-xr-x 18 wangchuanhai staff 576B 3 9 17:36 CHShareDeskdrwxr-xr-x 18 wangchuanhai staff 576B 3 10 00:39 CHShareHomedrwxr-xr-x 16 wangchuanhai staff 512B 3 8 00:25 CHShareMasterdrwxr-xr-x 18 wangchuanhai staff 576B 3 9 15:15 CHShareMinedrwxr-xr-x 8 wangchuanhai staff 256B 3 10 11:43 CHShareThird---------------------------------------------------------------------------------------------------------------------------------~/code/private/CHShare » cd CHShareThird ---------------------------------------------------------------------------------------------------------------------------------~/code/private/CHShare/CHShareThird(master) » ll total 24drwxr-xr-x 12 wangchuanhai staff 384B 3 10 11:32 CHShareThird-rw-r--r-- 1 wangchuanhai staff 643B 3 10 11:43 CHShareThird.podspecdrwxr-xr-x@ 5 wangchuanhai staff 160B 3 10 11:32 CHShareThird.xcodeproj-rw-r--r-- 1 wangchuanhai staff 213B 3 10 11:43 Podfile-rw-r--r-- 1 wangchuanhai staff 178B 3 10 11:43 upload.sh---------------------------------------------------------------------------------------------------------------------------------

执行CocoaPods的项目初始化

cd 到项目根目录,执行pod install

$ pod install
iOS模块化管理之CocoaPods实战

创建源码SDK

模块化工程的源码以SDK的形式提供给宿主工程(也就是模块工程本身)和主App以及其他需要依赖的工程。

选择初始化好的工程,用Xcode打开,File -> New -> Target -> Framework

Product Name: ${projectName} + SDK

iOS模块化管理之CocoaPods实战

创建资源bundle

Resource bundle作为单独的Target为SDK提供静态资源等的支持。

File -> New -> Target -> 选择macOS模块下的Bundle。由于Xcode只支持在macOS下创建bundle,故选择macOS模块下的Bundle选项。

Product Name: ${projectName} + Bundle

iOS模块化管理之CocoaPods实战

在刚创建好的CHShareThirdBundle文件夹下新建Assets.xcassets文件,作为图片等静态资源的容器。

另外,要将CHShareThirdBundle Targets的Base SDK属性修改成iOS支持。

需特别注意的,resource bundle这个SDK中需要将info.plist文件中的Executable file选项移除,不然会出现获取不到文件的情况。

iOS模块化管理之CocoaPods实战

创建framework脚本

将编译好的framework文件和bundle文件从模拟器的沙盒目录拷贝至工程的根路径,以方便CocoaPods上传到私有仓库。

File -> New -> Target -> 选择Other下的Aggregate。

iOS模块化管理之CocoaPods实战

添加执行脚本

iOS模块化管理之CocoaPods实战
#!/bin/sh#要build的target名TARGET_NAME=${PROJECT_NAME}if [[ $1 ]]thenTARGET_NAME=$1fiUNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}Upload/"
#创建输出目录,并删除之前的framework文件rm -rf "${UNIVERSAL_OUTPUT_FOLDER}"mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
#编译模拟器的Frameworkxcodebuild -target "${TARGET_NAME}SDK" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#拷贝framework到univer目录cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}SDK.framework" "${UNIVERSAL_OUTPUT_FOLDER}"#拷贝bundle到univer目录cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}Bundle.bundle" "${UNIVERSAL_OUTPUT_FOLDER}"
#打开合并后的文件夹open "${UNIVERSAL_OUTPUT_FOLDER}"

到此一个模块的基本配置工作就算完成,接下来需要调整一下资源的依赖关系,从系统层面不难理解,Demo工程(也就是模块项目本身)依赖SDK工程,SDK依赖Bundle资源。

接下来,就可以开开心心地撸代码了。

构建Cocoapods版本

podspec文件

修改version版本号,要与最终提交到git上的代码tag保持一致

增加vendored_frameworks指向工程根目录中script脚本拷贝的framework和bundle资源

添加工程中所依赖的第三方库和系统库等

Pod::Spec.new do |s|
s.name = "CHShareThird" s.version = "1.0.20210310" s.summary = "CHShareThird." s.description = <<-DESC this is CHShareThird DESC s.homepage = "https://gitee.com/ishadoo/CHShareThird" s.license = { :type => "MIT", :file => "FILE_LICENSE" } s.author = { "王传海" => "ishadoo@163.com" } s.platform = :ios, "10.0" s.source = { :git => "https://gitee.com/ishadoo/CHShareThird.git", :tag => s.version }
## 源码形式集成 # s.source_files = "CHShareThird/CHShareThird/**/*.{h,m}"
## 是否支持ARC s.requires_arc = true
## 构建的模块类型 s.vendored_frameworks = "CHShareThirdUpload/CHShareThirdSDK.framework" s.resources = "CHShareThirdUpload/CHShareThirdBundle.bundle"
## 依赖的第三方库以及framework资源 s.dependency "Masonry" s.framework = "UIKit" end

upload.sh文件

如下图所示,项目中添加一个UIViewController作为NavigationControler根视图,现将该模块封板上传到CocoaPods私有库。

iOS模块化管理之CocoaPods实战

编译通过后,先执行framework 拷贝脚本,然后执行该脚本构建到远端CocoaPods库.

执行前

iOS模块化管理之CocoaPods实战

执行后

脚本执行后在项目的根目录多了一个CHShareThirdUpload文件夹,其中包含CHShareThirdSDK.framework和CHShareThirdBundle.bundle这两个文件

iOS模块化管理之CocoaPods实战

代码封板,将代码上传到远程仓库,同时封版打tag,tag号要与CHShareThird.podspec中的version相一致。

此时准备工作完成。

执行upload.sh

~/code/private/CHShare/CHShareThird(master) » ll total 56drwxr-xr-x 8 wangchuanhai staff 256B 3 10 16:39 CHShareThird-rw-r--r-- 1 wangchuanhai staff 979B 3 10 17:13 CHShareThird.podspecdrwxr-xr-x@ 5 wangchuanhai staff 160B 3 10 16:41 CHShareThird.xcodeprojdrwxr-xr-x@ 5 wangchuanhai staff 160B 3 10 15:05 CHShareThird.xcworkspacedrwxr-xr-x 4 wangchuanhai staff 128B 3 10 15:29 CHShareThirdBundledrwxr-xr-x 6 wangchuanhai staff 192B 3 10 16:25 CHShareThirdSDK-rw-r--r--@ 1 wangchuanhai staff 1.1K 2 24 15:18 FILE_LICENSE-rw-r--r--@ 1 wangchuanhai staff 232B 3 10 16:33 Podfile-rw-r--r-- 1 wangchuanhai staff 270B 3 10 16:34 Podfile.lockdrwxr-xr-x 8 wangchuanhai staff 256B 3 10 16:34 Pods-rw-r--r-- 1 wangchuanhai staff 956B 3 10 14:53 README.en.md-rw-r--r-- 1 wangchuanhai staff 1.3K 3 10 14:53 README.md-rw-r--r-- 1 wangchuanhai staff 178B 3 10 14:50 upload.sh

执行脚本有时会出现执行权限问题,此时需要对upload.sh脚本授权

~/code/private/CHShare/CHShareThird(master) » ./upload.sh zsh: permission denied: ./upload.sh

授权

~/code/private/CHShare/CHShareThird(master) » chmod +x upload.sh 

再次执行脚本

~/code/private/CHShare/CHShareThird(master*) » ./upload.sh 

经过漫长的编译,会收到成功上传的信息,部分编译信息如下,

 ** BUILD SUCCEEDED **  Testing with `xcodebuild`.  -> CHShareThird (1.0.2021031001) - NOTE | xcodebuild: note: Using new build system - NOTE | xcodebuild: note: Building targets in parallel - NOTE | xcodebuild: note: Using codesigning identity override: - - NOTE | [iOS] xcodebuild: note: Planning build - NOTE | [iOS] xcodebuild: note: Constructing build description - NOTE | [iOS] xcodebuild: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 6.0, but the range of supported deployment target versions is 9.0 to 14.4.99. (in target 'Masonry' from project 'Pods') - NOTE | [iOS] xcodebuild: warning: Skipping code signing because the target does not have an Info.plist file and one is not being generated automatically. (in target 'App' from project 'App') - NOTE | [iOS] xcodebuild: ld: warning: ignoring file CHShareThird/CHShareThirdUpload/CHShareThirdSDK.framework/CHShareThirdSDK, building for iOS Simulator-i386 but attempting to link with file built for iOS Simulator-x86_64 - NOTE | [iOS] xcodebuild: ld: warning: ignoring file CHShareThird/CHShareThirdUpload/CHShareThirdSDK.framework/CHShareThirdSDK, building for iOS Simulator-arm64 but attempting to link with file built for iOS Simulator-x86_64
Updating the `ishadoo-specs' repo
$ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs pull Already up to date.
Adding the spec to the `ishadoo-specs' repo
$ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs status --porcelain ?? CHShareThird/ - [Add] CHShareThird (1.0.2021031001) $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs add CHShareThird $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs commit --no-verify -m [Add] CHShareThird (1.0.2021031001) [master 95fe617] [Add] CHShareThird (1.0.2021031001) 1 file changed, 29 insertions(+) create mode 100644 CHShareThird/1.0.2021031001/CHShareThird.podspec
Pushing the `ishadoo-specs' repo
$ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs push origin HEAD remote: Powered by GITEE.COM [GNK-5.0] To https://gitee.com/ishadoo/Specs.git 468cfbb..95fe617 HEAD -> master

至此,CHShareThird模块的第一个版本就成功上传到Cocoapods私有仓库。

查看远程仓库

跟踪一下远程仓库,不难发现新建的CHShareThird模块已经成功上传我们的私有仓库。

使用CHShareThird模块

在该主App的Podflie文件中添加如下依赖   pod 'CHShareThird'

# Uncomment this line to define a global platform for your projectplatform :ios, '10.0'
source 'https://gitee.com/ishadoo/Specs.git'source 'https://github.com/CocoaPods/Specs.git'source 'https://gitee.com/ishadoo/CHShareMine.git'
target 'CHShareMaster' do pod 'CHShareHome' pod 'CHShareMine', :git => 'https://gitee.com/ishadoo/CHShareMine.git', :branch => 'develop' pod 'CHShareDesk' pod 'CHShareThird'end
target 'CHShareSDK' do pod 'CHShareHome' pod 'CHShareMine', :git => 'https://gitee.com/ishadoo/CHShareMine.git', :branch => 'develop' pod 'CHShareDesk' pod 'CHShareThird'end

执行pod update

~/code/private/CHShare/CHShareMaster(develop*) » pod updateUpdate all podsUpdating local specs repositories $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs fetch origin --progress $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs rev-parse --abbrev-ref HEAD master $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/ishadoo-specs reset --hard origin/master HEAD is now at 95fe617 [Add] CHShareThird (1.0.2021031001) $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/master fetch origin --progress $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/master rev-parse --abbrev-ref HEAD master $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/master reset --hard origin/master HEAD is now at 5b4b6eecd2f8 [Add] TCNetwork 0.2.2 $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/gitee-ishadoo-chsharemine fetch origin --progress $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/gitee-ishadoo-chsharemine rev-parse --abbrev-ref HEAD master $ /usr/bin/git -C /Users/wangchuanhai/.cocoapods/repos/gitee-ishadoo-chsharemine reset --hard origin/master HEAD is now at ec3e546 updateAnalyzing dependenciesPre-downloading: `CHShareMine` from `https://gitee.com/ishadoo/CHShareMine.git`, branch `develop`Downloading dependenciesInstalling CHShareMine 1.0.2021030901Installing CHShareThird (1.0.2021031001)Generating Pods projectIntegrating client projectPod installation complete! There are 4 dependencies from the Podfile and 5 total pods installed.

此时CHShareThird成功地添加到了主App当中。


以上是关于iOS模块化管理之CocoaPods实战的主要内容,如果未能解决你的问题,请参考以下文章

ios开发xcode 8.3之CocoaPods的安装

iOS之深入解析Cocoapods的工作原理与源码分析

iOS之深入解析Cocoapods的工作原理与源码分析

译使用 CocoaPods 模块化iOS应用

iOS开发之ruby版本的升级与cocoapods的安装和使用

iOS开发之进阶篇(15)—— CocoaPods