编程技术记录

世界你好!

背景

合作项目,一方提供宿主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脚本

DebugiPhoneosTargetBuild 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试试

© Beli. All Rights Reserved.