Create by xinyuan 2020/06/12
- 前言:
我们经常会创建自己的私有库,然而我们经常会使用一个命令行就是
pod lib create ***
,这边文章就是简单的介绍他部分源码。
一、步骤简单了解
- 1、当我们在终端输入
pod lib create ***
后,会出现这样的界面 一般情况我们就会噼里啪啦的往下选择,生成一个我们想要的文件,这是我们一般的常规操作,而此刻我们暂停下来可以看看其提示,我们发现他是执行了一条克隆语句。对的他只是把远端的代码下载下来,然后在进行一系列的操作。
Cloning`https://github.com/CocoaPods/pod-template.git` into `Demo`
-
2、文件目录结构
从这个结构上面看,其实最重要的就是在setup里面的这些ruby
脚本。只是因为他区分处理了iOS、swift、Mac的,所以脚本才会有这么多。 -
3、demo工程
平时的那些就是通过已经现有的demo工程利用脚本进行了简单修改
二、部分代码展示
- 1、TemplateConfigurator.rb
# 这里算是一个主要的方法了,主要在这里做了语言上的区分以及采用哪个demo的方法。MessageBank.rb这个文件主要是进行一些在终端打印的提示处理类
def run
@message_bank.welcome_message
platform = self.ask_with_answers("What platform do you want to use?", ["iOS", "macOS"]).to_sym
#这里开始区分语言,因为语言不同,代码不同所以进行调用的脚本也是不同的
case platform
when :macos
ConfigureMacOSSwift.perform(configurator: self)
when :ios
framework = self.ask_with_answers("What language do you want to use?", ["Swift", "ObjC"]).to_sym
case framework
when :swift
ConfigureSwift.perform(configurator: self)
#假设我们这边进行了oc版本的选择,然后他开始执行ConfigureIOS下的perform方法进行处理
when :objc
ConfigureIOS.perform(configurator: self)
end
end
....
end
- 2、ConfigureiOS.rb
module Pod
class ConfigureIOS
attr_reader :configurator
def self.perform(options)
new(options).perform
end
def initialize(options)
@configurator = options.fetch(:configurator)
end
def perform
# 这里是选择一些选项,按照我们pod lib create 走下去的话,这些问题都会在命令行进行展示的
keep_demo = configurator.ask_with_answers("Would you like to include a demo application with your library", ["Yes", "No"]).to_sym
framework = configurator.ask_with_answers("Which testing frameworks will you use", ["Specta", "Kiwi", "None"]).to_sym
case framework
when :specta
configurator.add_pod_to_podfile "Specta"
configurator.add_pod_to_podfile "Expecta"
configurator.add_line_to_pch "@import Specta;"
configurator.add_line_to_pch "@import Expecta;"
configurator.set_test_framework("specta", "m", "ios")
when :kiwi
configurator.add_pod_to_podfile "Kiwi"
configurator.add_line_to_pch "@import Kiwi;"
configurator.set_test_framework("kiwi", "m", "ios")
when :none
configurator.set_test_framework("xctest", "m", "ios")
end
snapshots = configurator.ask_with_answers("Would you like to do view based testing", ["Yes", "No"]).to_sym
case snapshots
when :yes
configurator.add_pod_to_podfile "FBSnapshotTestCase"
configurator.add_line_to_pch "@import FBSnapshotTestCase;"
if keep_demo == :no
puts " Putting demo application back in, you cannot do view tests without a host application."
keep_demo = :yes
end
if framework == :specta
configurator.add_pod_to_podfile "Expecta+Snapshots"
configurator.add_line_to_pch "@import Expecta_Snapshots;"
end
end
prefix = nil
loop do
prefix = configurator.ask("What is your class prefix").upcase
if prefix.include?(' ')
puts 'Your class prefix cannot contain spaces.'.red
else
break
end
end
#这里需要利用到ProjectManipulator.rb文件进行demo工程上的修改,这里主要是讲部分信息传了过去,然后进行run方便的调用。
Pod::ProjectManipulator.new({
:configurator => @configurator,
:xcodeproj_path => "templates/ios/Example/PROJECT.xcodeproj",
:platform => :ios,
:remove_demo_project => (keep_demo == :no),
:prefix => prefix
}).run
# There has to be a single file in the Classes dir
# or a framework won't be created, which is now default
`touch Pod/Classes/ReplaceMe.m`
`mv ./templates/ios/* ./`
# remove podspec for osx
`rm ./NAME-osx.podspec`
end
end
end
- 3、ProjectManipulator.rb
#这里主要用到了xcodeproj这个组件,进行对xcode文件的修改,这里应该才是精髓,这里是涉及到对xcodeproj的使用。
def run
@string_replacements = {
"PROJECT_OWNER" => @configurator.user_name,
"TODAYS_DATE" => @configurator.date,
"TODAYS_YEAR" => @configurator.year,
"PROJECT" => @configurator.pod_name,
"CPD" => @prefix
}
#这个方法是拿到了项目的文件,然后进行文件内容的读取替换
replace_internal_project_settings
@project = Xcodeproj::Project.open(@xcodeproj_path)
#这里是添加.podspec、README.md、LICENSE文件
add_podspec_metadata
#这里是移除了demo工程以及重写Podfile文件
remove_demo_project if @remove_demo_target
@project.save
#这里是进行一些重命名的方法,这里他写的不太好的地方就是是固定类去改变了,例如,可以看到下面是demo中CPDAppDelegate的类名,如果这里可以改一下还是会好一点
# unless @remove_demo_target
# # change app file prefixes
# ["CPDAppDelegate.h", "CPDAppDelegate.m", "CPDViewController.h", "CPDViewController.m"].each do |file|
# before = project_folder + "/PROJECT/" + file
# next unless File.exists? before
# after = project_folder + "/PROJECT/" + file.gsub("CPD", prefix)
# File.rename before, after
# end
# # rename project related files
# ["PROJECT-Info.plist", "PROJECT-Prefix.pch", "PROJECT.entitlements"].each do |file|
# before = project_folder + "/PROJECT/" + file
# next unless File.exists? before
# after = project_folder + "/PROJECT/" + file.gsub("PROJECT", @configurator.pod_name)
# File.rename before, after
# end
# end
rename_files
#文件夹的命名修改
rename_project_folder
end
#这里部分细节代码可以尝试跑一下看看实现
- 4、TemplateConfigurator.rb
def run
...
#工程进行处理完之后,这里会回到TemplateConfigurator类中run一些公共的方法
# POD_LICENSE、POD_README.md、NAME.podspec、.travis.yml 配置修改,例如用户名时间等
replace_variables_in_files
#移除掉一些克隆下来之后没有用的文件,"./**/.gitkeep", "configure", "_CONFIGURE.rb", "README.md", "LICENSE", "templates", "setup", "CODE_OF_CONDUCT.md"
clean_template_files
# 更换README.md、LICENSE以及新的.podspec
rename_template_files
add_pods_to_podfile
customise_prefix
rename_classes_folder
ensure_carthage_compatibility
reinitialize_git_repo
run_pod_install
@message_bank.farewell_message
end
#这里部分细节代码可以尝试跑一下看看实现
三、结束语
按照cocoapods这一份demo,我们应该也可以实现一份脚本,实现通过脚本通过部分配置然后立刻得出一份具有基础配置的项目工程。这里主要修改的应该是ProjectManipulator.rb
文件,由于cocoapods用的demo工程已经是比较老版本的了,所以在替换过程中应该要注意下部分变量是否还存在,例如现在看到的在ProjectManipulator.rb
中rename_files
方法的scheme就是目前新的项目没有的。还有一点要注意的是,他是对就的demo进行修改,而不是新创建。
scheme_path = project_folder + "/PROJECT.xcodeproj/xcshareddata/xcschemes/"