最近组内在打包时,bundle exec pod install
命令频繁出现 clone 组件授权失败的情况:
1 | remote: HTTP Basic: Access denied |
开始以为 GitLab 的 ssh 服务不稳定,毕竟以前也出过类似的问题,但经过后续排查,发现是 GitLab CI 和 Jenkins 的 Git 凭证冲突了。
最近组内在打包时,bundle exec pod install
命令频繁出现 clone 组件授权失败的情况:
1 | remote: HTTP Basic: Access denied |
开始以为 GitLab 的 ssh 服务不稳定,毕竟以前也出过类似的问题,但经过后续排查,发现是 GitLab CI 和 Jenkins 的 Git 凭证冲突了。
目前掌柜团队内部缺少组件发布平台,每次 App 发版都需要组件负责人去发布自己名下涉及的组件。这中间存在组件间依赖以及发布时间差问题,上层组件需要依赖下层组件的发布,负责人之间沟通起来极为耗时。所以团队暂时没有限制私有源仓库的推送权限,当发布时间比较紧时,方便负责人绕过 lint, 直接推送 podspec 到私有源仓库。
虽然这种发布方式能节省一部分时间,但是容易出现下层组件 lint 失败向上层传递的情况。久而久之,lint 不通过的组件将会越来越多。为了尽量避免这种情况的发生,引入 CI 对组件进行 lint 监测是个不错的选择。
以上就是掌柜团队当初引入 CI 的初衷。不过 CI 能带来的便利远不止如此,当然,这都是后话了。
为了减少组件化后的工程集成时间,我们一般都会将三方库放到私有 GitLab 中,这也有利于开发者根据自家业务,对三方库进行定制包装。但是如果有些三方库更新较慢,以至于让新版本的 Xcode 产生很多警告,这就比较烦了,因为大部分情况下,更改三方库并不是一个明智的选择。
Podfile 提供了 inhibit_all_warnings!
以屏蔽所有 pod target 的警告,但其中也包括了非三方组件。同时,Podfile 提供了 inhibit_warnings
去针对单个 pod 的编译警告进行控制,比如:
1 | pod 'SSZipArchive', :inhibit_warnings => true |
以上代码只会屏蔽 SSZipArchive 组件的警告,这比较符合我们的诉求。不过 inhibit_warnings
只会禁止当前 pod 的警告,并不会一同处理依赖组件的警告,这就要求我们在 Podfile 中显式依赖所有三方组件,并且设置 inhibit_warnings
。
虽说 CocoaPods 有 cocoapods-packager 这个插件可以生成二进制版本,但这个库的维护者似乎并不活跃,很多 issue 和 pr 过了一两年还堆积着没处理。于是我决定试试 Carthage ,不过不利用 Cartfile 生成依赖,还是用的 CocoaPods 那一套。
要让组件支持 Carthage ,工程里只需要有一个 shared framework target
即可。针对 CocoaPods 生成的工程,我们先在 Podfile 里面设置 use_frameworks!
,来满足 framework target
。
经过对旧项目持续地拆分,组件库已经初具规模,组件粒度也变得越来越小,管理组件的成本也逐渐显现出来。目前团队采用的方式是,每个组件由特定的负责人进行管理,只有责任人才拥有 master 分支的访问权限,并且打 tag、发布组件版本都需要由负责人操作。
当一个特性涉及到的组件库不多时,直接在钉钉上通知相关负责人升级下组件版本即可,然后将各个组件的新版本重新写入 Podfile。刚开始我会查下负责人是谁,然后在群组里罗列他需要升级的组件。但是修改的组件一多就比较麻烦了,如果直接把涉及的所有组件名往群组里一扔,组员有时候也会看漏了。
于是我就有了下面的想法:
用脚本获取 Podfile 指向分支的组件名,然后去本地私有源获取组件的作者,再匹配本地存储的组员名,最后将负责人和所负责的组件发送到钉钉群组中。
在没有实行组件化的项目中,经常会在 AppDelegate 看到各类初始化代码,这一部分代码一般用以配置某些 key 以及 secret ,或者开启某些服务,常见的有第三方推送、统计分析、IM服务等。当然,也有可能是开启一些自身的服务,比如 log 日志、 数据库初始化等。当一个 App 达到一定体量后, 未经整理的 AppDelegate 可能会变得臃肿。那么在实行组件化之后,该如何处理这部分代码呢?
对于这个问题的思考,起源于云风的这篇文章 浮点运算潜在的结果不一致问题,其中有几个评论我比较在意:
1 | stirp: |
Block 和 Delegate 是对象间传递消息的常用机制,这两个机制可以说是各有千秋。 Delegate 可以很方便把目标动作的执行过程划分为多个方法,以展现不同时间节点下特定的操作; Block 则擅长处理一个回调多个落点的情况,并且它可以通过捕捉上下文信息,来达到减少创建额外变量,集中消息处理逻辑的目的。
结合以上两种通信方式的特点,我们可以添加一些额外的桥接处理,让 Delegate 机制也能享有 Block 机制所拥有的部分优点。桥接处理的核心就是用 Block 实现委托方法。
说起 Objective-C runtime 在实际项目中的应用,可能很多人第一时间联想到的是黑魔法 method swizzling 、 associated objects 、 KVC / KVO 以及各种灵活的 runtime api 。这几种技术在开发过程中或多或少都会涉及到 ,也的确为开发者立下了汗马功劳,尤其在解决一些棘手问题时,屡试不爽。不过同样是 runtime 重要组成部分的消息转发却较少听人提及,这篇文章就来扒一扒它在不同应用场景中的精彩表现。