iOS——写一个快速定位问题的脚本

本文介绍了一种在CI环境中自动给App图标添加版本、分支和commit信息的方法。通过编写shell脚本并利用ImageMagick工具,实现了在Debug构建环境下对图标进行非破坏性的标记。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

你是否见过?

  1. 你是否见过测试人员或者自己在 CI 上 install 了一个版本,发现了 BUG 后,突然忘了自己下的是 CI 上的哪一个 commit 的包?
  2. 你是否见过下面这个东西:

写一个这样一个脚本

可以写这样一个脚本,它能做到:

  1. 在 Build 的过程中在 App Icon 的表面覆盖上 Build 号、分支名、commit version 的 hash 值
  2. 不影响原本的 App Icon 图标源文件
  3. 区分 ReleaseDebug,只在 Debug 环境下 Build 项目时执行脚本

Do it

ImageMagick

做后端的同学们,大多知道 ImageMagick

使用 ImageMagick 可以创建、编辑、合成或转换图片。它可以读和写各种格式的图像(超过 200 种格式)包括 PNG、JPEG、JPEG - 2000、GIF、TIFF、DPX、EXR、WebP、Postscript、PDF、SVG。ImageMagick 可以调整、翻转、镜像、旋转、扭曲、剪切和转换图像、图像色彩调整,适用于各种特殊效果,或绘制文本、线、多边形、椭圆和贝塞尔曲线。

通过 shell command 就可以轻易使用以上功能。


让我们来看一些基本的。这是我们准备好的 120*120 的原图:

cd 到图片所在的目录,执行以下命令,给图片添加高斯模糊效果:

convert original.png -blur 10x8 blurred.png
复制代码

完成图:


继续,执行以下命令从 坐标 (0,60) 剪切成 120*60 的图片,

convert blurred.png -crop 120x60+0+60 cropped-blurred.png
复制代码

完成图:


继续,给图片添加文字水印『zhoulingyu』,参数包括:背景不填充颜色、白色字体、字体大小 12、居中显示文字、文字为『zhoulingyu』:

convert -background none -fill white -pointsize 12 -gravity center caption:"zhoulingyu" cropped-blurred.png +swap -composite label.png
复制代码

完成图:


继续,将上面得到的剪切好的带水印的 label.png 和 原图 original.png 合成在一起:

composite label.png original.png finished-image.png
复制代码

完成图:

OK,我们得到了想要的效果图。

参数参考

给出一些 ImageMagic 的常用用法:

  1. 查看图片信息
identify original.png 
original.png PNG 120x120 120x120+0+0 8-bit sRGB 46c 2.58KB 0.010u 0:00.000
复制代码
  1. 格式转换
convert original.png original.jpg 
复制代码
  1. 编辑图片大小
convert original.png -resize 200x200 resize-image.png 
复制代码
  1. 裁剪
# 从坐标 (0,0) 裁剪 100*100 的图像
convert original.png -crop 100x100+0+0 crop.png  
复制代码
  1. 旋转
convert original.png -rotate 45 rotate.png 
复制代码
  1. 合并图像
# 给图片添加水印
convert original.png -compose over watermark.png -composite new-image.png  
复制代码
  1. 高斯模糊
convert -blur 80x5 original.jpg blur.png
复制代码

-blur radiusxsigma,两个分别是高斯模糊需要的两个参数,具体可以查看 blur 参数使用

ImageMagick 可以实现 N 多效果,像油画、噪声、散射、旋涡,都不在话下。

除了基本的效果,还有一些比较常用的参数:

参数名使用规范说明用例
-background-background color设置背景色-background white
-pointsize-pointsize value设置字体等大小-pointsize 12
-gravity-gravity type为其他命令附加 gravity,比如设置文字添加位置居中。-gravity Center
-geometry-geometry geometry设置即将处理图像的坐标位置-geometry +0+60 -geometry Center

当然这些都可以在 官方文档 找到。

shell 脚本

1. 基本设置

知道 ImageMagic 如何使用,剩下来写脚本就思路清晰多了。

在工程 Target -> Build Phases 中新建一个 Run Script,我们可以给它起名 generate auxiliary icon,这样稍后容易在 Report Navigator 观察。

现在我们可以开始编写我们的脚本 auxiliary_icon.sh

2. 理思路

写伪代码通常能够帮助我自己更清晰的写代码:

// 1. 判断执行 Build 的机器是否安装了 ImageMagic
//    |- 如果没有安装:提示安装,退出脚本
//    |- 如果安装:继续执行
// 2. 获取 commit 号 hash 值、分支名、build 号,并将其拼接成一个字符串
// 3. 判断编译环境
//    |- 如果是 Release 环境:提示当前是 Release 环境,退出脚本
//    |- 如果是非 Release 环境:继续执行
// 4. 获取 Plist 中 CFBundleIconFiles 的数量
// 5. 根据数量循环,执行调用『生成记号图方法』


// 『生成记号图方法』 
// function generateIcon() {
// 1. 模糊图片
// 2. 截取图片下半部分
// 3. 添加 commit+brach+build 组成的字符串在截取图片上
// 4. 合成截取图片和原图
// 5. 清除多余图片
// }
复制代码

伪代码写好了,开始编写正式代码:

  1. 判断执行 Build 的机器是否安装了 ImageMagic

which 一下就知道

convertPath=`which convert`
# 判断 convertPath 文件是否存在
if [ ! -f ${convertPath}]; then
echo "==============
WARNING: 你需要先安装 ImageMagick!!!!:
brew install imagemagick
=============="
exit 0;
fi
复制代码
  1. 获取 commit 号 hash 值、分支名、build 号,并将其拼接成一个字符串

PlistBuddy 可以用于读取 Plist 文件,通过描述路径就可以找到你想知道的 Key 对应的 Value。 ${INFOPLIST_FILE} 是 xcodebuild 提供的变量(具体可以参考 Build settings reference)提供了编译后 info.plist 的路径。

commit=`git rev-parse --short HEAD`
branch=`git rev-parse --abbrev-ref HEAD`
buildNumber=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_FILE}"`
caption="${buildNumber} \n${branch}\n${commit}"
复制代码
  1. 判断编译环境
# Release 不执行
echo "Configuration: $CONFIGURATION"
if [ ${CONFIGURATION} = "Release" ]; then
exit 0;
fi
复制代码
  1. 获取 Plist 中 CFBundleIconFiles 的数量

在编译后的 info.plist 中,可以找到如下结构:

这里记录了所有的 Icon files。查看 plist 的原格式,可以看到原始的 key 是什么。通过 PlistBuddy 和 路径 CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles 可以输出 value。

| wc -l 可以统计输出行数。

icon_count=`/usr/libexec/PlistBuddy -c "Print CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles" "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" | wc -l`
复制代码

要注意的是, /usr/libexec/PlistBuddy -c "Print CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles" "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" 输出结果是这样的:

输出一共是 五行,所以获得的结果是 5。

那么真实的 CFBundleIconFiles count 其实是:

real_icon_index=$((${icon_count} - 2))
复制代码

刚开始,我也没有注意。可想而知心情如何 =_=。

  1. 根据数量循环,执行调用『生成记号图方法』
for ((i=0; i<$real_icon_index; i++)); do
# 找到 icon 名
icon=`/usr/libexec/PlistBuddy -c "Print CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles:$i" "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"`

# 调用 generateIcon 方法,传入 icon 名
generateIcon "${icon}@2x.png"

done
复制代码
  1. generateIcon 方法
function generateIcon() {
    originalImg=$1

    cd "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"

    # 验证存在性
    if [[ ! -f ${originalImg} || -z ${originalImg} ]]; then
    return;
    fi

    # 进入编译后的工程目录
    cd "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/"

    # 添加高斯模糊
    convert ${originalImg} -blur 10x8 blur-original.png

    # 截取下部分
    width=`identify -format %w ${originalImg}`
    height=`identify -format %h ${originalImg}`
    height_0=`expr ${height} / 2`
    height_1=$((${height} - ${height_0}))
    convert blur-original.png -crop ${width}x${height_0}+0+${height_1} crop-blur-original.png

    # 加字
    point_size=$(((8 * $height) / 58))

    convert -background none -fill white -pointsize ${point_size} -gravity center caption:"${caption}" crop-blur-original.png +swap -composite label.png

    # 合成
    composite -geometry +0+${height_0} label.png ${originalImg} ${originalImg}

    # 清除文件
    rm blur-original.png
    rm crop-blur-original.png
    rm label.png
}
复制代码

代码清单

最终的代码清单放在了 Github 上:

ZLYWatermarkIcon

参考

Command-line Tools:Convert 使用ImageMagick添加图片水印-Linux krzysztofzablocki/IconOverlaying Overlaying application version on top of your icon 我的ImageMagick使用心得 高斯模糊的算法 Build settings reference Shell脚本编程30分钟入门


有什么问题都可以在博文后面留言,或者微博上私信我,或者邮件我 coderfish@163.com

博主是 iOS 妹子一枚。

希望大家一起进步。

我的微博:小鱼周凌宇

### iOS 脚本编程自动化工具概述 对于 iOS 开发者来说,选择合适的脚本或自动化工具可以极大地提高开发效率并减少重复劳动。以下是几种常见的 iOS 脚本和自动化工具及其特点: #### 1. Marathon Marathon 是一种专门用于 Swift 的轻量级脚本自动化工具[^1]。它允许开发者使用 Swift 编脚本来处理各种任务,例如运行单元测试、生成代码片段以及管理持续集成流程。由于 Swift 的强大类型系统和支持现代语法的特点,Marathon 提供了一种更高效的方式来进行脚本。 ```swift // 使用 Marathon 创建一个简单的 Swift 脚本 import Foundation let greetingMessage = "Hello, this is a Swift script running via Marathon!" print(greetingMessage) func runTests() { let testCommand = Process() testCommand.launchPath = "/usr/bin/xcodebuild" testCommand.arguments = ["test", "-project", "YourProject.xcodeproj"] do { try testCommand.run() } catch { print("Error while executing tests: \(error)") } } runTests() ``` 上述示例展示了如何通过 Swift 和 Marathon 来实现基本的任务调度功能。 --- #### 2. Fastlane Fastlane 是另一个广泛使用的 iOS 自动化工具,专注于简化移动应用发布过程中的复杂操作。它可以自动执行诸如证书管理、截图生成、App Store 提交等工作流。虽然主要面向部署阶段,但它也支持扩展到其他类型的自动化任务中。 ```ruby # fastlane 配置文件 (Fastfile) lane :beta do increment_build_number(xcodeproj: "MyApp.xcodeproj") # 增加版本号 build_app(scheme: "ReleaseScheme") # 构建应用程序 upload_to_testflight # 将 IPA 文件上传至 TestFlight end ``` 此 Ruby 脚本定义了一个名为 `beta` 的流水线,该流水线会依次增加构建编号、打包 App 并将其分发给内部团队成员进行 Beta 测试[^4]。 --- #### 3. Airtest 尽管 Airtest 主要被设计成跨平台 UI 自动化框架,并且通常应用于 Android 或 Web 应用程序的场景下[^3],然而其核心能力——基于图像匹配技术来定位界面组件的功能同样适用于某些特定需求下的 iOS 设备模拟器环境交互。如果遇到难以通过传统方法访问控件的情况,则可能考虑采用这种方法作为补充手段之一。 注意:Airtest 对于真机的支持有限,在实际项目里需谨慎评估适用性。 --- #### 4. Python 结合 Allure 报告 除了原生解决方案外,还可以借助外部语言如 Python 实现更加灵活多样的定制方案。比如结合 pytest 插件生成详尽美观的 HTML 格式的 allure 测试报告[^2]。这种方式特别适合那些已经熟悉 Python 生态圈的企业和个人开发者群体。 ```python def test_login_success(): """验证登录成功""" assert login(username="admin", password="password"), "Login failed" if __name__ == "__main__": import pytest pytest.main(["--alluredir=./results"]) # 执行测试并将结果保存到指定目录 ``` 以上是一个简单例子说明怎样利用 PyTest 运行单个函数形式的单元测试案例同时记录日志数据以便后续分析查看。 --- ### 总结 每款工具有各自的优势领域及局限之处,具体选用哪一款取决于当前项目的实际情况和技术栈偏好等因素综合考量决定。无论是追求极致性能优化还是希望降低学习门槛快速上手,总有一款能满足您的期望!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值