当前位置: 首页 > 编程日记 > 正文

CocoaPods原理(一)

CocoaPods介绍

CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具。利用 CocoaPods,可以定义自己的依赖关系 (称作 pods),并且随着时间的变化,以及在整个开发环境中对第三方库的版本管理非常方便。

CocoaPods 背后的理念主要体现在两个方面。首先,在工程中引入第三方代码会涉及到许多内容。针对 Objective-C 初级开发者来说,工程文件的配置会让人很沮丧。在配置 build phases 和 linker flags 过程中,会引起许多人为因素的错误。CocoaPods 简化了这一切,它能够自动配置编译选项。

其次,通过 CocoaPods,可以很方便的查找到新的第三方库。当然,这并不是说你可以简单的将别人提供的库拿来拼凑成一个应用程序。它的真正作用是让你能够找到真正好用的库,以此来缩短我们的开发周期和提升软件的质量。

核心组件

CocoaPods是用 Ruby 写的,并由若干个 Ruby 包 (gems) 构成的。在解析整合过程中,最重要的几个 gems 分别是:CocoaPods/CocoaPods, CocoaPods/Core, 和 CocoaPods/Xcodeproj (是的,CocoaPods 是一个依赖管理工具 -- 利用依赖管理进行构建的!)。

CocoaPods 是一个 objc 的依赖管理工具,而其本身是利用 ruby 的依赖管理 gem 进行构建的。

CocoaPods/CocoaPod 这是是一个面向用户的组件,每当执行一个 pod 命令时,这个组件都将被激活。该组件包括了所有使用 CocoaPods 涉及到的功能,并且还能通过调用所有其它的 gems 来执行任务。

CocoaPods/Core Core 组件提供支持与 CocoaPods 相关文件的处理,文件主要是 Podfile 和 podspecs。

CocoaPods/Xcodeproj 这个 gem 组件负责所有工程文件的整合。它能够对创建并修改 .xcodeproj 和 .xcworkspace 文件。它也可以作为单独的一个 gem 包使用。如果你想要写一个脚本来方便的修改工程文件,那么可以使用这个 gem。

Ruby 概述

Ruby 的语法具有强大的表现力,并且其使用非常灵活,能快速实现我们的需求,这里简单介绍一下 Ruby 中跟CocoaPods有关的特性。

方法

简单的方法

def method_name (var1=value1, var2=value2)expr..
end
复制代码

ruby中的方法以'def'开头,以'end'作为结尾,我们可以为参数设置默认值,如果方法调用时未传递必需的参数则使用默认值,上例中的value1value2就是默认值。

Ruby 代码在调用方法时可以省略括号。

可变数量的参数

def sample (*test)puts "参数个数为 #{test.length}"for i in 0...test.lengthputs "参数值为 #{test[i]}"end
end
sample "Zara", "6", "F"
复制代码

以上实例的输出结果为:

参数个数为 3
参数值为 Zara
参数值为 6
参数值为 F
复制代码

数据类型--Hash

哈希(Hash)是类似 "key" => "value" 这样的键值对集合。哈希类似于一个数组,只不过它的索引(或者叫"键")不局限于使用数字,Hash 的索引几乎可以是任何对象。

Hash 虽然和数组类似,但却有一个很重要的区别:Hash 的元素没有特定的顺序。 如果顺序很重要的话就要使用数组了。

pod 'SwViewCapture', :git=>'git@github.com:startry/SwViewCapture.git', :branch=>'master'
复制代码
def pod(name = nil, *requirements)unless nameraise StandardError, 'A dependency requires a name.'endcurrent_target_definition.store_pod(name, *requirements)
end
复制代码

pod方法后面跟着的参数就是一个Hash的对象,写成key-value的形式就是

{":git": "git@github.com:startry/SwViewCapture.git",":branch": "'master'"
}
复制代码

block

Ruby 对函数式编程范式的支持是通过 block,Ruby 中的 block 也是一种对象,所有的 Block 都是 Proc 类的实例,也就是所有的 block 可以作为参数传递,返回。

这边构造一个block传参的方法

def target(name, &proc)definition = TargetDefinition.new(name, parent)proc.call() if proc
end
复制代码

除了声明block参数作为参数传入,还可以使用关键字yield在ruby中表示调用块。

yield 主要用于隐式 block 回调,ruby 方法默认可以不声明 block,在其内部可通过 yield 回调。yield 会调用外部传入的 block,block_given? 用于判断当前方法是否传入了 block。

def target(name)definition = TargetDefinition.new(name, parent)yield if block_given?
end
复制代码

Ruby中do ~end之间的部分称为块,也可以写为{..}

所以这个target方法可以以这种形式调用:

target('PodSample') {pod('SDWebImage', '~> 4.4.2')
}
复制代码

也可以使用我们常见的形式调用:

target('PodSample') dopod('SDWebImage', '~> 4.4.2')
end
复制代码

eval

最后一个需要介绍的特性就是 eval 了,早在几十年前的 Lisp 语言就有了 eval 这个方法,这个方法会将字符串当做代码来执行,也就是说 eval 模糊了代码与数据之间的边界,iOS开发过程中也会使用eval执行js代码。

 eval "1 + 2 * 3" => 7
复制代码

我们在执行Podfile文件的相关操作时,比如常用的installupdate,都会用eval在上下文中执行Podfile文件中的“代码”。

Podfile&Podfile.lock的解析

Podfile

在介绍完ruby的语言特性之后,大家对于理解Podfile文件应该没有什么问题了。

CocoaPods内部定义了一些配置方法,把方法参数转化为内部Hash变量的属性。

def source(url)$hash_value['source'] = url
enddef target(target)$hash_value['target'] = target
enddef pod(pod)pods = $hash_value['pods']pods = [] if pods == nilpods << pod$hash_value['pods'] = pods
end
复制代码

下面说一下CocoaPods在解析完Podfile的结果是怎么样的。

执行eval(Podfile.content)的同时会生成一个Podfile类的对象,这个类有重要的两个属性:

  1. 一个是Hash类型的internal_Hash,保存全局的一些配置,比如sourceworkspace
  2. 另一个是TargetDefinition类的root_target_definitions对象,TargetDefinition类之间有parent和children之间的联系,通过root_target_definitions对象可以遍历到Podfile文件所有声明的target对象,target对象会保存传入该target方法中block的所有参数。

Podfile.lock

Podfile.lock文件是用数据描述语言YAML编写的,YAML(YAML Ain’t Markup)是一种简洁的非标记语言,以数据为中心,使用空白,缩进,分行组织数据,从而使得表示更加简洁易读,其可以与json互转,CocoaPods内部是把Podfile.lock文件解析成Hash类型,从而进行参数数据查询和与Podfile文件中的参数进行对比。

看源码发现Cocoapods不仅支持ruby形式的podfile文件,也支持YAML形式的podfile文件配置方式。

PODS:
  - AFNetworking (3.1.0):
    - AFNetworking/NSURLSession (= 3.1.0)
    - AFNetworking/Reachability (= 3.1.0)DEPENDENCIES:
  - AFNetworking (= 3.1.0)SPEC REPOS:
  https://github.com/cocoapods/specs.git:
    - AFNetworkingSPEC CHECKSUMS:
  AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67PODFILE CHECKSUM: a06ca71d7960a7bf4f294d3ad147e0e67528a467COCOAPODS: 1.5.3
复制代码
{"PODS":[{"AFNetworking (3.1.0)":["AFNetworking/NSURLSession (= 3.1.0)","AFNetworking/Reachability (= 3.1.0)"]}],"DEPENDENCIES":["AFNetworking (= 3.1.0)"],"SPEC REPOS":{"https://github.com/cocoapods/specs.git":["AFNetworking"]},"SPEC CHECKSUMS":{"AFNetworking":"5e0e199f73d8626b11e79750991f5d173d1f8b67"},"PODFILE CHECKSUM":"a06ca71d7960a7bf4f294d3ad147e0e67528a467","COCOAPODS":"1.5.3"
}
复制代码

总的来说ruby形式podfile的解析就是调用方法,把各类参数配置转化为Hash数据,如果是YAML形式的数据转化就更便捷了,本身就是key-value形式的数据。

参考链接:
CocoaPods 都做了什么?
pod install和pod update背后那点事

相关文章:

1055 The World‘s Richest

开始的做法是&#xff0c;对于每一个case&#xff0c;都在整个person数组内进行遍历&#xff0c;把所有年龄符合要求的都放进一个临时数组&#xff0c;然后对临时数组进行排序&#xff0c;再根据要求的数目输出。但是这么做会有一个测试用例因为超时而通不过。 穷则思变。于是…

IOS时间传递机制简记

事件传递顺序&#xff1a;自定义View -- > UIview --> RootViewController --> UIWindow -->UIApplication -->Appdelegate -->nil 注&#xff1a; //分发事件&#xff0c;将当前的触摸事件分发给当前对象的下一个响应者 //如果当前对象处理了当前事件&am…

HDOJ2270(How Many Friends Will Be Together With You)

#include <iostream>using namespacestd;const int MAX 1000005;intfr[MAX];intmain(){ int n, i, tt, sum; while(cin>>n) { for(i 1; i < n; i) fr[i] i;//初始化&#xff0c;一开始每个都是独立的&#xff0c;并无朋友 …

在linux环境下重启oracle数据库,解决密码过期的问题

&#xff08;1&#xff09; 以oracle身份登录数据库&#xff0c;命令&#xff1a;su – oracle &#xff08;2&#xff09; 进入Sqlplus控制台&#xff0c;命令&#xff1a;sqlplus /nolog &#xff08;3&#xff09; 以系统管理员登录&#xff0c;命令&#xff1a;connect /as…

1075 PAT Judge

1. 这一题一开始&#xff0c;为了同一个人的数据更新得方便&#xff0c;我把id从字符串转化成整数&#xff0c;作为数组下标&#xff0c;但是注意了&#xff0c;每个学生还是要有字符串的id属性(根据下标得到)&#xff0c;因为后面一旦排序&#xff0c;数组下标就毫无意义了。 …

MySQL 错误代码和消息

本章列出了当你用任何主机语言调用MySQL时可能出现的错误。首先列出了服务器错误消息。其次列出了客户端程序消息。 B.1. 服务器错误代码和消息 服务器错误信息来自下述源文件&#xff1a; 错误消息信息列在share/errmsg.txt文件中。“%d”和“%s”分别代表编号和字符…

一步步学习汇编(8)之指令

要理解ret,retf&#xff0c;call指令&#xff0c;必须要先理清以下汇编基础知识&#xff1a; 一&#xff0e; [bx]和内存单元<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />[bx]是什么呢&#xff1f; 和[0]有些类似…

【转】不分主副卡!全网通5.0时代到来

全网通在今天已经不是噱头了&#xff0c;它经历了有5年时间&#xff0c;从过去的全网通1.0到现在的全网通5.0&#xff0c;可以说有这长足的发展。今年&#xff0c;小米率先了支持全网通5.0的小米MIX 2S和红米Note5&#xff0c;可以双卡双待4G&#xff0c;一边打电话一边打游戏不…

1048 Find Coins(散列解法)

1. 开始测试点3答案错误&#xff0c;看参考书发现是&#xff0c;读题时根据硬币最大面值500设置的数组大小&#xff0c;但是后来会用总面值减去硬币面值&#xff0c;这个大小在[1,999)&#xff0c;因此散列表的大小应该设为1010。 2. 学会了一个小技巧。main函数可以不止一处r…

简单ThreadPool实现

由于最近需要用多线程处理一些问题&#xff0c;一开始我用了.net默认的ThreadPool&#xff0c;感觉不是很适合。于是我自己实现了一个简单的ThreadPool。 写的比较简单&#xff0c;有兴趣的朋友一起看看&#xff0c;共同改进。 代码主要由ThreadPoolEx,WorkItem,WorkQueue组成。…

CSS中强大的EM

使用CSS也好久了&#xff0c;但一直都是在使用“px”来设置Web元素的相关属性&#xff0c;未敢使用“em”。主要原因是&#xff0c;对其并不什么了解&#xff0c;只知道一点概念性的东西&#xff0c;前段时间在项目中要求使用“em”作为单位设置元素&#xff0c;所以从头对“em…

16.1、python初识面向对象(1)

初识面向对象 楔子 你现在是一家游戏公司的开发人员&#xff0c;现在需要你开发一款叫做<人狗大战>的游戏&#xff0c;你就思考呀&#xff0c;人狗作战&#xff0c;那至少需要2个角色&#xff0c;一个是人&#xff0c; 一个是狗&#xff0c;且人和狗都有不同的技能&#…

1080 Graduate Admission

1.因为这道题第一次认真想了高考录取的规则&#xff0c;对学生按照先总分再gE的原则进行从高到低排序&#xff0c;排名允许重复。再按照排名高到低对每个学生的每个志愿进行遍历&#xff0c;当一个学生处理完&#xff0c;再进行下一个。 2.由于最后是要输出学生的原始序号&…

vc++实现无进程无DLL无硬盘文件无启动项的ICMP后门后门程序

客户端 #include <winsock2.h>#include <stdio.h>#include <stdlib.h> #pragma comment(lib,"ws2_32.lib") char SendMsg[256]; /* The IP header */typedef struct iphdr {unsigned int h_len:4; //4位首部长度unsigned int version:4; //IP版本…

arm linux 启动之一:汇编启动到start_kernel

描述arm linux启动的概要过程&#xff0c;以S5PV210(Cortex A8)为例&#xff0c;本文描述第一个阶段。 一、arm linux的引导 uboot在引导arm linux&#xff08;uImage镜像&#xff09;到SDRAM之后&#xff0c;通过bootm命令对uImage镜像的64个字节头进行解释&#xff0c;获取li…

Sql Server 因为触发器问题导致数据库更新报错“在触发器执行过程中引发了错误,批处理已中止”的问题处理...

在维护一个非常旧的项目时&#xff0c;由于该项目版本已经非常老了&#xff0c;而且在客户现场运行的非常稳定&#xff0c;更要命的是本人目前没有找到该项目的代码&#xff0c;为了处理一个新的需求而且还不能修改程序代码&#xff0c;于是决定从数据库入手&#xff0c;毕竟该…

1070 Mooncake

1. 一道典型的贪心题&#xff0c;策略是尽可能地多出售单价高的月饼。 2. 开始有一个用例没有通过&#xff0c;看了参考书&#xff0c;说是质量虽然给的都是整数&#xff0c;但是为了计算不出错&#xff0c;需要声明为浮点型。改了以后果然就通过了&#xff0c;但是个中原理不…

Java数组合并,完成排序,从时间复杂度,和空间复杂度考虑

2019独角兽企业重金招聘Python工程师标准>>> 提供方法&#xff0c;直接调用&#xff0c;支持任意个数组的合并成一个数组&#xff0c;并且完成排序&#xff0c;每个数组元素个数不定。需要提供两个方法&#xff0c;分别做到时间复杂度最低、空间复杂度最低。并说明两…

WPF中Auto与*的差别

Auto 表示自己主动适应显示内容的宽度, 如自己主动适应文本的宽度,文本有多长,控件就显示多长. * 则表示按比例来分配宽度. <ColumnDefinition Width"3*" /> <ColumnDefinition Width"7*" /> 相同,行能够这样定义 <RowDefinition Height&qu…

个人电脑优化方案

2009年4月13日 文件删除--系统默认磁盘清理--批处理清除无用文件--使用优化软件如优化大师 Codeecho off echo 正在清除系统垃圾文件&#xff0c;请稍等 del /f /s /q %systemdrive%\*.tmp del /f /s /q %systemdrive%\…

1037 Magic Coupon

1. 贪心算法题&#xff0c;贪心策略&#xff1a;两组乘子相乘&#xff0c;每个数字至多用一次&#xff0c;希望得到最大的乘积。那么让A组绝对值最大的正数和B组最绝对值最大的正数相乘&#xff0c;次大的和次大的相乘……同样的让A组绝对值最大的负数和B组绝对值最大的负数相乘…

综合布线系统入门及应用(二)

一、工程材料用量估计 1、信息模块及水晶头用量统计 信息插座与工位数量1:1&#xff0c;在增加5%的余量 跳线&#xff1a;一般需要2条&#xff0c;工位信息面板到设备&#xff0c;交换机到配线架&#xff0c;每根条线2个水晶头&#xff0c;预留10%-15%。 2、线槽用量统计 根据办…

如何查看服务器有多少网站--免费工具

一台虚拟主机上到底有多少个网站或者说同一ip下有多少个域名和网站&#xff1f;这是站长们都很关心的&#xff0c;因为这样可以知道你的站到底和谁是邻居&#xff0c;有时候如果你和百度黑名单上的垃圾站在同一空间下&#xff0c;你也会受到牵连。 那么怎 ...中间左侧广告 一台…

二分法在算法题中的4种常见应用(cont.)

目录 1.查找单调序列中是否存在满足某条件的元素 2.寻找序列中第一个(最后一个)满足某条件的元素的位置 3.给定一个定义在[L,R]上的单调函数f(x)&#xff0c;求方程f(x)0的根 4.快速幂的递归和迭代求法 1.查找单调序列中是否存在满足某条件的元素 //二分区间为左闭右闭的[l…

Minimum Path Sum

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time. 格子取数问题&#xff0c;另dp[i][j]表示走…

Thorntail 2.2.0提供从WildFly Swarm自动迁移的特性

自6月底宣布把WildFly Swarm2018.5.0改名为Thorntail2.0.0以来&#xff0c;Red Hat在8月中旬以后的三个周里发布了Thorntail 2.1.0版本和2.2.0版本。除了许多Bug修复外&#xff0c;尤其是和MicroProfile相关的&#xff0c;新特性还包括&#xff1a;\\符合MicroProfile 1.3\通过…

Depth Bias

在dx中的depth bias要以如下形式调用 inline DWORD F2DW( float f ) { return *((DWORD*)&f); } m_pD3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(1)); m_pD3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(0.001)); 总之&#xff0c;奇怪的api。转载…

(C++)用upper_bound函数取代自己写的二分查找

int a[maxn];int j upper_bound(ai1,an,(long long)a[i]*p)-a; 以上代码的作用是 在a[i1]~a[n-1]找到第一个大于a[i]*p的数&#xff0c;将其下标返回给j 注意&#xff1a; 1.函数是左闭右开的 2.末尾要减去数组的坐标a 3.不加long long强制类型转换可能丢分

gsoap使用总结

WebService、soap、gsoap基本概念 WebService服务基本概念&#xff1a;就是一个应用程序&#xff0c;它向外界暴露出一个可以通过web进行调用的API&#xff0c;是分布式的服务组件。本质上就是要以标准的形式实现企业内外各个不同服务系统之间的互调和集成。 soap概念&#xff…

SQL时间相关 - SQL日期,时间比较

SQL Server 中时间比较 例子: select count(*) from table where DATEDIFF ([second], 2004-09-18 00:00:18, 2004-09-18 00:00:19) > 0 说明 select DATEDIFF(day, time1 , time2) 对应示例语句如下 select DATEDIFF(day, 2010-07-23 0:41:18, 2010-07-23 23:41:18) …