CocoaPods对三方库的管理探究

CocoaPods是iOS开发中经常被用到的第三方库管理工具,我们有必要深入了解一下它对项目产生了什么影响,以及它是如何管理这些库的。

使用pod安装三方库

我们新建一个不带测试模块的名为FFDemo的Swift项目,它的目录结构是这样的

1
2
3
4
5
6
7
8
9
10
11
├── FFDemo
│   ├── AppDelegate.swift
│   ├── Assets.xcassets
│   ├── Base.lproj
│   ├── Info.plist
│   ├── SceneDelegate.swift
│   └── ViewController.swift
└── FFDemo.xcodeproj
├── project.pbxproj
├── project.xcworkspace
└── xcuserdata

然后我们执行pod init创建一个Podfile模板,在里面引入这两个三方库:

1
2
3
4
5
6
7
8
9
target 'FFDemo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

# Pods for FFDemo
pod 'MJRefresh', '~> 3.5.0'
pod 'Moya'

end

成功执行pod install之后我们就将这两个库引入到了项目,这时项目目录变成了这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
├── FFDemo
│   ├── AppDelegate.swift
│   ├── Assets.xcassets
│   ├── Base.lproj
│   ├── Info.plist
│   ├── SceneDelegate.swift
│   └── ViewController.swift
├── FFDemo.xcodeproj
│   ├── project.pbxproj
│   ├── project.xcworkspace
│   └── xcuserdata
├── FFDemo.xcworkspace
│   └── contents.xcworkspacedata
├── Podfile
├── Podfile.lock
└── Pods
├── Alamofire
├── Headers
├── Local\ Podspecs
├── MJRefresh
├── Manifest.lock
├── Moya
├── Pods.xcodeproj
└── Target\ Support\ Files

从目录看,除了pod init引入了Podfile,其余三部分内容:FFDemo.xcworkspace、Podfile.lock、Pods目录都是由pod install之后生成的。我们下面重点讲下这三部分内容。

CocoaPods安装的内容

xcworkspace文件

该文件下包含一个叫contents.xcworkspacedata的文件,它的内容是这样的:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:FFDemo.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

使用xml格式将依赖包含在标签内。

xcworkspace是一个项目容器,当有多个project需要相互依赖时可以用xcworkspace将它们组织起来。pod在首次安装三方库时会生成一个叫Pods.xcodeproj的project管理三方库,然后将该project和主项目的project通过workspace进行关联。这样我们就可以在主工程里引入三方库了,而且三方库由Pods.xcodeproj统一管理,不会对我们原项目产生任何干扰。

Podfile.lock

Podfile.lock文件的内容是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
PODS:
- Alamofire (5.3.0)
- MJRefresh (3.5.0)
- Moya (14.0.0):
- Moya/Core (= 14.0.0)
- Moya/Core (14.0.0):
- Alamofire (~> 5.0)

DEPENDENCIES:
- MJRefresh (~> 3.5.0)
- Moya

SPEC REPOS:
trunk:
- Alamofire
- MJRefresh
- Moya

SPEC CHECKSUMS:
Alamofire: 2c792affbdc2f18016e08fdbcacd60aebe1ba593
MJRefresh: 6afc955813966afb08305477dd7a0d9ad5e79a16
Moya: 5b45dacb75adb009f97fde91c204c1e565d31916

PODFILE CHECKSUM: 073f3d6d9f03e6a76838ca3719df48ae6cc01450

COCOAPODS: 1.9.3

因为Podfile文件里可以不指定版本号,而版本信息又很重要,于是就有了Podfile.lock,它里面记录完整的版本信息和依赖关系。它的内容包含以下几大块

PODS

PODS是指当前引用库的具体版本号,可以发现我们并没有引入Alamofire,但在PODS里确有它。这是因为Moya中依赖了它,Moya里定义了一个subspec叫Core,这是Moya/Core写法的由来。pod是通过各个库的podspec文件找到对应依赖的,这里可以简单看下Moya的部分podspeec文件内容Moya.podspec

1
2
3
4
5
6
7
8
9
Pod::Spec.new do |s|
s.default_subspecs = "Core"

s.subspec "Core" do |ss|
ss.source_files = "Sources/Moya/", "Sources/Moya/Plugins/"
ss.dependency "Alamofire", "~> 5.0"
ss.framework = "Foundation"
end
end

DEPENDENCIES

DEPENDENCIES为pod库的描述信息,这里内容是同Podfile里的写法。因为我们指定了MJRefresh的版本号,并没有指定Moya的版本号,所以这里内容也是一样的。

SPEC REPOS

这里描述的是仓库信息,即安装了哪些三方库,他们来自于哪个仓库。

trunk是共有仓库的名称,它的地址是https://github.com/CocoaPods/Specs.git,外部使用的三方库大都来自于这里。通常我们还会依赖一些公司内部的私有库,私有库的信息也会显示在这里。

SPEC CHECKSUM

这里描述的是各个三方库的校验和,校验和的算法是对当前安装版本的三方库的podspec文件求SHA1。比如MJRefresh的校验和:6afc955813966afb08305477dd7a0d9ad5e79a16。我们安装的MJRefresh的版本为3.5.0,它在本地的podspec文件路径为:~/.cocoapods/repos/trunk/Specs/0/f/b/MJRefresh/3.5.0/MJRefresh.podspec.json

这个路径可以通过在安装库时增加--verbose参数在输出日志里查看。我们对该文件内容通过openssl求sha1摘要:

1
2
$ pod ipc spec ~/.cocoapods/repos/trunk/Specs/0/f/b/MJRefresh/3.5.0/MJRefresh.podspec.json | openssl sha1
$ 6afc955813966afb08305477dd7a0d9ad5e79a16

因为是对podspec.json内容求sha1,所以只要内容发生一点变化,得出的校验和就将大不相同,而这也是校验和设计的目的:podspec文件发生变化意味着版本信息发生了变化,就需要重新同步代码。

大家可能注意到了,我们通常制作私有pod,控制配置信息的文件是podspec格式的,为什么本地文件变成了json格式?

这是因为json格式兼容性更高也更容易批量处理,官方Spec仓库的所有库配置文件都是被转成json格式的。在我们制作私有库的时候是可以直接以podspec的格式推到远程仓库的,但后续解析文件时pod内部检索还是会把它转成json格式。上面的命令是包含了podsepc转json的命令的,转json命令如下:

1
$ pod ipc spec ModuleName.podspec

PODFILE CHECKSUM

这个校验和是针对Podfile内容的校验和,如果Podfile内容改变了,该值也会跟着改变。计算方法为:

1
$ openssl sha1 filePath/Podfile

COCOAPODS: 1.9.3

这个代表当前使用的CocoaPod版本号,远程版本管理应该要保证大家使用的pod版本号一致。

Pods

Manifest.lock

Manifest.lock是Podfile.lock的副本,它是在Pods目录里面。它的作用是这样的,我们通常是不把Pods文件放到版本管理里面,而把Podfile.lock放到版本管理里面。这时对于拉取代码之后是否需要更新pod,就可以通过对比本地的Manifest.lock和远程Podfile.lock是否相同即可。

Targets Support Files

Pods安装的依赖是这样的组织形式

一个Pods的Project下面有三个Targets,其中三个是安装的依赖库,最后一个Pods-FFDemo是关联三个库的Framework,也即是Pods这个Project的Targets。

Pods-Demo Framework

先看这个Demo的Framework,它会被用于工程项目的引用依赖

这个库不会被打进包里,因为Do Not Embed代表并不是包含的关系。

这个工程下的配置文件有这些:

许可协议文件
两个以acknowledgements命名的文件是用于管理pod库的许可协议,即三方库必须带有的LICENSE文件,这也是为什么我们在制作pod时会要求我们指定软件协议。

Framework文件
这里还包含了用于管理Module的modulemap和umbrella.h文件。modulemap是对Module的声明文件,制作Framework我们总是需要该文件,它的内容如下:

1
2
3
4
5
6
framework module Pods_FFDemo {
umbrella header "Pods-FFDemo-umbrella.h"

export *
module * { export * }
}

其指向了一个umbrella的头文件,这是制作Framework必须的头文件,modulemap和umbrella.h会在创建Module时自动生成,不建议手动修改其关系。

dummy.m文件

这其实是一个空的.m文件

1
2
3
4
5
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_FFDemo : NSObject
@end
@implementation PodsDummy_Pods_FFDemo
@end

那为什么要有这个东西呢,包括所有的三方库的包里也会包含一个dummy文件。我在stackoverflow找到了一个解释:Xcode的编译是依赖.m文件的,如果一个库里没有.m文件,将不会被编译,为了防止这种情况就会在每个库里增加一个空的.m文件。

xcconfig文件

xcconfig文件是Build Setting配置项的文件形式,它的优先级大于Xcode内的Build Setting。看一个pod生成的debug模式下的xcconfig文件。

1
2
3
4
5
6
7
8
9
10
11
12
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Moya"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Moya/Moya.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" -framework "Foundation" -framework "MJRefresh" -framework "Moya"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

xcconfig还有个作用是设置参数,比如我们比较熟悉的PODS_ROOT=${SRCROOT}/PODS,它代表项目根目录下的PODS文件目录。另外两项用于帮助我们在项目中查找三方库的FRAMEWORK_SEARCH_PATHSHEADER_SEARCH_PATHS也是在改文件内部定义的,这些配置会体现到Build Settings里面:

三方库的Framework

image-20201114150517801

各个三方库也都有一些配置文件,他们文件格式基本一致,上图是Moya的配置文件。Moya的xcconfig文件里有一行这个:

1
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire"

用于告诉Moya在引用Alamofire时应该去哪里找这个依赖。

Build Phases

这里是设置编译阶段配置的地方,当首次pod install成功之后,这里会多几个[CP]开头的配置项(CP即CocoaPods缩写),它们都是由CocoPods添加的脚本内容,执行顺序从上到下。

New System Build

在讲编译脚本之前简单说下New Build System。

New Build System是Xcode10之后苹果推出的新的构建系统,新的构建系统对编译流程的优化做了很多工作,虽然到Xcode12仍兼容旧版的Legacy Build System,但其已经被标记为移除,我们的项目和库都应该使用新版的构建系统进行构建。和新的构建系统随之而来的是在运行脚本时增加的输入输出列表。

这是为了控制是否每次编译都需要执行对应脚本,input和output文件可以是单个文件形式,如果文件过多可以放到格式为xcfilelist的文件列表里。

如果没有提供input和output,则每次构建都会运行该脚本。如果提供了,则会在以前从未运行过、某个输入文件被更改或某个输出文件丢失的情况下再次运行。

注意这些是构建脚本的默认逻辑,Xcode还提供了Run Scripts的自定义行为,默认勾选项:Based on dependency analysis,即代表上述逻辑。如果提供了输入输出还需要每次运行,关闭该选项即可。

[CP] Check Pods Manifest.lock

该脚本位于较上方,如果没有Dependencies,开始编译就会执行该脚本,它的内容如下:

1
2
3
4
5
6
7
8
diff "${PODS_PODFILE_DIR_PATH}/Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
if [ $? != 0 ] ; then
# print error to STDERR
echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2
exit 1
fi
# This output is used by Xcode 'outputs' to avoid re-running this script phase.
echo "SUCCESS" > "${SCRIPT_OUTPUT_FILE_0}"

作用是比较Podfile.lockManifest.lock文件是否相同,如果不同就输出错误信息:error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.,并执行退出,这会导致后续项目报错,无法继续编译。

该错误较常见,出现于拉取远端代码,远端pod依赖于本地不一致的情况。这时我们可以根据提示,执行pod install命令,根据Podfile及远端Podfile.lock生成新的Manifest.lock文件。

[CP] Copy Pods Resources

这个一般在以静态库引入的三方库切里面包含资源的话会添加该脚本,其作用是将三方库的资源文件拷贝至项目中。

它的完成是通过运行以下脚本进行的:

1
"${PODS_ROOT}/Target Support Files/Pods-FFDemo/Pods-FFDemo-resources.sh"

Pods-FFDemo-resources.sh文件在Pods目录内,该脚本内有个关键函数install_resource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
install_resource()
{
if [[ "$1" = /* ]] ; then
RESOURCE_PATH="$1"
else
RESOURCE_PATH="${PODS_ROOT}/$1"
fi
if [[ ! -e "$RESOURCE_PATH" ]] ; then
cat << EOM
error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
EOM
exit 1
fi
case $RESOURCE_PATH in
*.storyboard)
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.xib)
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.framework)
echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
echo "$RESOURCE_PATH" || true
echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
;;
esac
}

删除了一部分日志内容,其内部主要是一个switch语句,根据资源文件的类型进行不同的同步操作。这里重点说下几种重要格式文件的处理方式。

storyboard和xib格式

这两项资源文件是需要编译处理的,利用ibtool命令分别转成sotryboardc和nib格式。

xcassets格式

这里的图片最终会被打包到Assets.car供程序使用,需要使用actool。

Bundle、plist、png等资源

其他类的资源是会走到switch语句最后出口,进行资源路径赋值给$RESOURCES_TO_COPY,在后面的代码中通过rsync命令,将资源同步到构建包的目录。

该脚本会打印很多日志,在使用CocoaPods时如果遇到资源相关的问题都可以遵循错误日志来这里推测定位错误原因。

[CP] Embed Pods Frameworks

该处脚本是直接运行Pods-FFDemo-frameworks.sh

1
"${PODS_ROOT}/Target Support Files/Pods-FFDemo/Pods-FFDemo-frameworks.sh"

可能你还记得上面说的pod会把多个库的依赖做成一个合并的库,但该库是以依赖的形式引入主工程,但是程序的运行时需要这些库,我们打包时就需要将各个库Embed到项目里,而做这个工作的就是该脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Copies and strips a vendored framework
install_framework()
{
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"

# other code...

# Strip invalid architectures so "fat" simulator / device frameworks work on device
if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
strip_invalid_archs "$binary"
fi

# Resign the code if required by the build settings to avoid unstable apps
code_sign_if_enabled "${destination}/$(basename "$1")"
}

脚本内容主要是调用install_framework函数,将framework内容同步到构建包里。在该函数里还有几个关键方法,strip_invalid_archs用于去除无用架构,code_sign_if_enabled用于framwork签名。

博客搭建介绍及腾讯云服务器配置

前置说明

一直以来都是用GithubPage搭建的博客,因为服务器在国外,访问速度一直比较慢,再后来有一批服务器被墙掉了导致国内网络环境直接无法访问。这里可以多说一句,GithubPage跟Github用的可以不是同一IP地址服务器,被墙很多是通过锁定IP进行的,GithubPage搭建博客有些可以访问有些不可以,就是因为某些IP被封了,如果更换IP也是可以解决的,但访问速度还是不够快。前段时间看到腾讯云服务器打折,就考虑如果想保证国内的访问速度还是要将服务器迁移到国内来。

这篇文章的作用是对搭建博客做一个整体介绍,对博客中用到的方案进行一些比较,有些会写的比较简略还需要再转到别文章去看,另外重点会写一下迁移腾讯云及域名备案需要做的具体操作。

博客的搭建一般需要关注这五个部分:博客框架、域名、服务器、图床、Markdown工具。各个环节都有免费和付费版本的选择,一般来说免费能满足基本需求,付费则能提供更优质的体验,如何选择就看大家的需求了。这五部分的对比如下:

付费版本 免费版本
博客框架 Wordpress(部分内容付费) Hexo/Jekyll
域名 万网/腾讯云 freenom/dot.tk
内容托管平台 阿里云/腾讯云 GithubPage/GiteePage
图床 七牛/又拍 Github/Gitee
Markdown工具 MWeb Typora

接下来会围绕这五部分展开说明。

阅读更多

HLS及M3U8介绍

背景

MP4是我们常见的视频格式,往往我们在播放服务器视频时直接就是请求的MP4视频源。但其实这样并不好,MP4头文件[ftyp+moov]较大,初始化的播放需要下载完整的头文件并进行解析,之后再下载一定长度的可播视频片段才能进行播放。另外随着视频尺寸的增大头文件也会不断变大,这个初始播放时间也会更长。针对这种情况需要一种能加快视频初始解析的方法,HLS就是苹果提出的用于解决这种问题的方案。

阅读更多

一位iOS开发者的进阶之旅

背景

这篇文章来源于v2ex上的一个帖子:”iOS开发有什么国人写的比较好的书籍推荐?”(原文链接)。这里汇总的基本都是lujie2012的回答,另外我还附带了一些他与别人的讨论内容。虽然帖子题目是推荐iOS书籍,但设计内容已经超出了这个题目,在我看来其中还迸发出很多有意思的观点,所以就想把内容整理出来。在经过其本人同意之后,有了如下内容,希望对大家有所帮助。

阅读更多

iOS面试总结(2020年6月)参考答案

上个月发了这篇iOS面试总结(2020年6月),没想到挺受大家欢迎,本来是没打算为它写答案,但有几个人建议我最好出一篇答案,提的人多了我就答应了下来。因为最近比较忙,断断续续总算补完了,就有了这篇文章,希望它对大家还有用处。这些都属于参考答案,如果大家感觉有不对不准确的地方也欢迎指出,我会及时更新。

阅读更多

iOS面试总结(2020年6月)

都说今年互联网行情很差,作为被大家喊了好几年“iOS开发没人要了”的iOS行情更差。那真实情况是什么样的呢,以我的经历给大家分析下。应某个朋友建议,去掉这一句啊,目前iOS岗位还是挺多的,你可以这么想只要苹果爸爸不倒,iOS开发就不会没人要。但另一方面,招聘方对iOS开发的要求是在不断提高的,我们不能固步自封,满足现状,只有不断学习,不断进步,才能保持自身竞争力。

我的面试的阶段基本都在6月份,准备的阶段则要再往前推个半个月吧。期间约到了不少一二线互联网公司面试机会,前期由于准备不足也错失了一些机会,在之后的面试中不断总结经验,越来越有信心了,最终选择了爱奇艺。整体来看求职情况还算可以,不是很好但也不是很差,其中会带有一定运气成分,所以要换工作的话一定不要裸辞。

这里总结下这段时间的面试经历和一些心得,后面会附上期间遇到的面试题,大家可以尝试作答一下。

阅读更多

iOS面试备战-多线程

iOS面试中多线程绝对是最重要的知识点之一,它在日常开发中会被广泛使用,而且多线程是有很多区分度很高的题目可供考察的。这篇文章会梳理下多线程和GCD相关的概念和几个典型问题。因为GCD相关的API用OC看着更直管一些,所以这期实例就都用OC语言书写。

阅读更多

iOS面试备战-网络

计算机网络是计算机科学与技术专业的必修课,也是移动端,前端,后端都会涉及到的知识点,同时它也是iOS面试中大概率会出现的问题。所以准备面试的话,网络相关的知识点一定不能错过。这里总结了一些我认为有用的和最近面试遇到的网络相关知识点。

去年写过一篇《图解TCP/IP》总结的文章,也可以对着看下。

阅读更多

Swift进阶黄金之路(二)

image-20200511230812677

Swift进阶黄金之路(一)

上期遗留一个问题:为什么 rethrows 一般用在参数中含有可以 throws 的方法的高阶函数中。

我们可以结合Swift的官方文档对rethrows再做一遍回顾:

A function or method can be declared with the rethrows keyword to indicate that it throws an error only if one of its function parameters throws an error. These functions and methods are known as rethrowing functions and rethrowing methods. Rethrowing functions and methods must have at least one throwing function parameter.

返回rethrows的函数要求至少有一个可抛出异常的函数式参数,而有以函数作为参数的函数就叫做高阶函数。

这期分两方面介绍Swift:特性修饰词和一些重要的Swift概念。

阅读更多

如何通过静态分析提高iOS代码质量


随着项目的扩大,依靠人工codereview来保证项目的质量,越来越不现实,这时就有必要借助于一种自动化的代码审查工具:程序静态分析

程序静态分析(Program Static Analysis)是指在不运行代码的方式下,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,验证代码是否满足规范性、安全性、可靠性、可维护性等指标的一种代码分析技术。(来自百度百科)

词法分析,语法分析等工作是由编译器进行的,所以对iOS项目为了完成静态分析,我们需要借助于编译器。对于OC语言的静态分析可以完全通过Clang,对于Swift的静态分析除了Clange还需要借助于SourceKit

Swift语言对应的静态分析工具是SwiftLint,OC语言对应的静态分析工具有Infer和OCLitn。以下会是对各个静态分析工具的安装和使用做一个介绍。

阅读更多
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×