背景
合作项目,一方提供宿主App,一方提供动态库。双方囿于合规而不能为对方提供源码,所以双方提供的产物都是二进制产物。
运行时双方融合是没有问题的,但是对开发(尤其是动态库开发方)是不友好的。
当然,这场景要是在其他操作系统是没有什么大问题的。但对于iOS而言,因为苹果的硬性限制,真机环境调试是有些麻烦的。为解决开发阶段的调试需求,本文提供了一种思路并实践可行。
一些准备
- 开发者证书(调试)是必需的
- Xcode ,本文成文时使用的是13.4.1
- fastlane 工具,本文使用其重签名工具
手动调试
在介绍一键调试前,先大致介绍下如何手动调试。
若要在真机环境调试,需要先将部署到真机的所有可执行文件进行签名,这包括App主程序和动态framework
获取开发者证书列表
运行命令,获取可用的证书列表
security find-identity -v -p codesigning
结果一般是十六进制字符串和证书名字,例如
1) 十六进制串 "Apple Development: xxxxx(yyyyyyy)"
1 valid identities found
动态库重签名
codesign -f -s 证书标识(十六进制串) xxxx.framework
ipa包重签名
本文使用fastlane工具
# 安装fastlane
sudo gem install fastlane
安装成功后,执行重签名
fastlane sigh resign
#然后安装提示输入ipa包文件路径、证书文件路径
#期间也可填写证书的十六进制串
特别注意:重签名证书必需使用开发证书
。
重签名成功后,获得同名的ipa包,使用Xcode提供的Devices and Simulators
工具将ipa包安装到iPhone真机中
附加到进程
在真机上启动App
然后使用Xcode 提供的Debug -> Attach to Process
工具,将动态库附加到App进程中,正常情况下是就可以了进行调试了。
一键调试
一键调试的原理和过程和手动调试是类似的,只不过把一些工作自动化了
解压包
将重签名的ipa包解压,获得里面的Payload,找到对应的宿主App(一般名字为xxxxx.app)
创建新动态Target
新建Target不需要侵入其他Target的工程配置。
假设新建Target就叫做DebugiPhoneosTarget
,打开DebugiPhoneosTarget的scheme进行编辑
Edit Scheme -> DebugiPhoneosTarget -> Run -> Info -> Executeable -> Other
, 选择解压后宿主App
另外,编辑Scheme时,最好去掉最下方的“Share”选项(即不共享这个Scheme配置,避免git仓库管理时频繁发生冲突)
配置好后,直接点击Xcode Run是可以直接启动宿主App。如果能成功启动宿主App,那么一键调试就成功了一半。
配置Build Phase脚本
在DebugiPhoneosTarget
的Build Phase
里面新建一个Run Script Phase
,内容为sh $SRCROOT/debug.sh 一些参数
或者python $SRCROOT/debug.py 一些参数
($SRCROOT是工程目录,一些参数见下文)。当然,你可以使用其他语言类型的脚本,本文使用python脚本。
在debug.py中,主要就做了件事:
1、将Xcode构建生成的动态framework复制到宿主App/Frameworks目录中
2、对新生成的动态framework进行重签名
其实,还可以有第3件事,就是复制图片等资源文件,不过这就看具体的项目工程了。
debug.py中的核心代码
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
import os
CONFIGURATION_BUILD_DIR = sys.argv[1] # 构建产物输出目录
EXPANDED_CODE_SIGN_IDENTITY = sys.argv[2] # 签名证书的十六进制串
# 动态framework路径
frameworkName = xxxxx
frameworkPath = xxxxxx
# 宿主App的路径
hostAppPath = xxxxxx
# 复制framework
src = os.path.join(frameworkPath, frameworkName)
dst = os.path.jons(hostAppPath,frameworkName ,frameworkName)
func_copy(src,dst) # func_copy自定义的复制函数
#复制Info.plist 特别提醒Info.plist里面的内容必须是framework自己的,否则会影响重签名,导致运行失败
src = os.path.join(frameworkPath, "Info.plist")
dst = os.path.jons(hostAppPath,frameworkName ,"Info.plist")
func_copy(src,dst) # func_copy自定义的复制函数
#重签名
dst = dst = os.path.jons(hostAppPath,frameworkName )
os.system("codesign -f -s 证书标识(十六进制串) " + dst)
脚本中CONFIGURATION_BUILD_DIR和EXPANDED_CODE_SIGN_IDENTITY就是上文提到的一些参数
,需要主动传入,幸好Xcode 提供了环境变量宏,所以Build Phase脚本内容更新如下:
python $SRCROOT/debuy.py $CONFIGURATION_BUILD_DIR $EXPANDED_CODE_SIGN_IDENTITY
或者
sh $SRCROOT/debug.sh $CONFIGURATION_BUILD_DIR $EXPANDED_CODE_SIGN_IDENTITY
好了,再次点击Xcode Run试试