使用动态framework封装微信SDK实践2019-11-14

需求

对外提供一个SDK,功能是拉起微信小程序。

分析

  • 实现原理:在将要开发的SDK中,封装微信的SDK,通过微信SDK,从而达到拉起微信小程序的目的

  • 以前项目中,接入过微信SDK,是1.8.4版本的,使用了其中的分享图片到朋友圈的功能,比较顺利,是通过CocoaPod实现的,比较省心。

  • 随着iOS13的发布,现在的微信SDK升级到了1.8.6.1,增加了通用链接功能。并且通用链接是必选项,初始化函数增加了参数,否则就失败。
    [WXApi registerApp:APP_ID universalLink:UNIVERSAL_LINK];
    尝试过绕开这个通用链接,比如用百度的网址占位,这个函数一直返回NO

  • 说实话,通用链接真的很麻烦,看看微信给的介绍文章,说了一大堆,还没把问题说清楚。并且通用链接只是一个用Safari浏览器来打开app,比较鸡肋。说是增加安全性,这里也用不到。这里只是简单拉起微信小程序就可以了,不需要回传信息。
    关于openSDK1.8.6的更新说明

  • 提供了一个鸡肋功能,导致以前的版本不能用,也不考虑兼容性,微信的SDK做得真的很差。折腾了好几天,最终还是决定用相对简单易用的1.8.4,避开繁琐而没用的通用链接。

  • 网上说iOSSDK一般都是静态库,比如微信提供的SDK就是.a形式的静态库。我也试着封装了一下,发现使用起来很麻烦。比如我们提供的静态库叫my.a,用户使用的时候,要把my.a和对应的头文件my.h导入工程。由于my.a用到了微信的libWeChatSDK.a,所以用户也要把libWeChatSDK.a和配套的头文件导入工程。另外,libWeChatSDK.a还用到了很多系统库,微信文档不准确,自己查了好久的百度才link成功。这部分工作,用户也要重复一遍,想想都麻烦。

企业微信截图_894f5cc0-cc1d-43fc-846e-4fbab3c5a10f.png

既然这样,封装一层my.a又有什么意义,直接使用libWeChatSDK.a不就行了?

  • 封装成动态framework的话,至少使用libWeChatSDK.a时遇到的麻烦事只要做一遍就好了,这样才有封装的意义。

结论:使用动态framework封装WeChatSDK1.8.4实现拉起微信小程序的功能

开发动态framework

Setp1: 创建framework工程

framework的名字为工程名字,Xcode的菜单路径为File->New->Project...,在弹出菜单中,类型选择framework

企业微信截图_af4ebfbd-6e81-472e-8a92-6e89493db8c4.png

工程创建完成后,会自动生成一个和framework同名的h文件,这个文件是必须的,不能删除。

企业微信截图_0bd3e7f9-4b21-40ab-b547-527075ec5f80.png

Setp2: 修改输出文件

  • 默认情况下,只有与framework同名的h文件才能输出。如果项目不大,有这么一个输出文件就够了。但是,只有一个h文件不是很方便,可以用一个继承自NSObject的类代替,名字和framework同名。在头文件中定义输出函数。
企业微信截图_8add109c-e94f-4402-a0bb-76e0bbe754dc.png
  • 外部可以使用的文件在Build Phases -> Headers标签下,从Project部分移动到Public部分
企业微信截图_1ba5ccb5-ead8-4f9f-aec7-db2f8f3b6afe.png

Step3:导入微信SDK

  • 这里选用的是WeChatSDK1.8.4,以前从微信开发者平台下的,这个版本不需要通用链接,比较方便。现在网上能下的版本是WeChatSDK1.8.6.1,要求通用链接,用起来很麻烦,并且向前不兼容,效果很差,抛弃不用。

  • 微信SDK是静态的.a文件,将整个文件夹通过Xcode菜单File->Add files to ...就可以了。

  • 新建一个以NSObject为基类的自定义类,这里是KJTWeiXin,通过调用微信SDK的相关函数,完成拉起微信小程序的功能。

  • 在输出文件,这里是KJTUrlSdk.m,调用刚才的实现,完成的功能实现的导出工作。

企业微信截图_9b730ab9-3209-4970-aaef-c56d056ae40d.png

Step4:创建调试Target

  • framework是不能直接使用的,需要一个调用者APP。这里采用Target的方式(菜单路径File->New->Target...),名字,在framework名字后面加-Sample后缀,(这里是),类型就选最简单的单页面工程。
企业微信截图_6a7f0596-a7a0-4e6c-ba8d-e03a33cbdfe3.png
  • 建立项目依赖。使用者,(这里是KJTUrlSdk-Sample),依赖framework,(这里是KJTUrlSdk)。
企业微信截图_2e75a0b0-4e72-40b0-af4b-3d25b8ceca67.png

合并framework

生成的framework要么是真机的,要么是模拟器的,很不方便。用命令行也比较烦,用脚本的方式比较好。

  • Build Phase中的New Run Script Phase可以添加自动运行的脚本
企业微信截图_58d63202-320f-4197-8a9d-0b55fceeb8b3.png
  • 脚本内容如下:
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
open "${DEVICE_DIR}"
open "${SRCROOT}/Products"
fi
  • 每次运行都会生成一遍,模拟器和真机至少运行一次之后,在工程根目录下的Product文件夹下就是合并过的framework,真机和模拟都能用。
企业微信截图_38d58813-c1a5-4394-9143-3db2260fc698.png

Step5: Demo工程

  • 创建一个独立的工程,使用自己开发的framework。这个工程要和前面的开发工程完全独立。名字可以加-Demo后缀,(这里是KJRUrlSdk-Demo

  • 通过菜单Flie->Add files to ... 将合并过的framework添加进来。

注意:如果要提交苹果市场,只能用真机版本的framework,否则会出错。

  • 在General标签下,将framework的载入格式改为Embed&Sign,否则会奔溃。
企业微信截图_318404b0-b634-446d-9024-3b7bfcf20e36.png

如果不改,崩溃信息一般如下:
dyld: Library not loaded: @rpath/KJTUrlSdk.framework/KJTUrlSdk
Referenced from: /var/mobile/Containers/Bundle/Application/CFEEFAD2-1BF3-4D29-967B-42CAAB7C4811/KJTUrlSdk-Demo.app/KJTUrlSdk-Demo
Reason: image not found

最后的样子:经过以上各步骤,最后的文件结构样子大致如下

企业微信截图_46c1c67c-ca66-408c-8b50-0b37fb30f330.png

微信SDK依赖系统库

  • 微信 WeChatSDK1.8.4依赖如下系统库
企业微信截图_071c4e89-edfd-42bb-b371-fda4f64fc562.png
  • 如果不添加这些系统库,会出现链接错误,并且这些问题,微信的开发文档并没有完全说清楚。只能百度,一个个试过去,比较麻烦。
    导入微信支付报错解决

  • 使用动态framework包含一个静态.a的好处是上面那些依赖可以在framework内部处理掉,最终使用者,这里是KJTUrlSdk-Demo,就不需要再考虑这些麻烦事了。

注册函数导致崩溃。

  • 由于是MTA库中的剪贴板和其他程序竞争,导致崩溃。只要不打开MTA就好了。
    WXApi registerApp:@"xxx" enableMTA:NO];

[__NSArrayM enqueue:]: unrecognized selector sent to instance

  • WeChatSDK1.8.5之后的版本解决了这个问题。
企业微信截图_9af8874b-d246-40ce-a716-20915a36e158.png

检查微信是否安装函数不可用

这是因为微信SDK使用[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"weixin://"]]方式来检查是否安装微信。iOS9之后,要在Plist中加白名单才可以用。不然这个函数始终返回NO

企业微信截图_f9a9e6c0-4a8a-4a42-bcd9-bb8627a8c788.png

[WXApi isWXAppInstalled]

应用BundleID信息校验不通过

  • 如果使用者APPbundle ID,(这里是KJTUrlSdk-DemoKJTUrlSdk-Sample),和微信后台配置的bundle ID不一致,就会弹这个信息框,小程序跳转也有异常。但是,微信API函数执行还是成功的。
企业微信截图_c5762cab-aeca-4548-a837-7a65b9c81af1.png
企业微信截图_4af8688e-f225-4038-b029-e6f06d434355.png

framework的版本号

  • framework工程创建的时候,会自动给出两个关于版本的全局变量,一个是double型的,一个是char数组
企业微信截图_6f17cd00-b1df-47c5-bd55-4e439f73c8d2.png
  • 这两个变量对应的是Target->General下的Build,并不是通常理解的Version
企业微信截图_662decb7-c7c7-4fd6-b585-58bb9fc730d2.png
  • double型的数字只能显示两位,比如设置1.2.3.4,显示1.200000;字符型的能显示全,不过会加上很多前缀。比如Build配置为1.2.3.4,通过NSLog输出:
    NSLog(@"数字版本号:%f", KJTUrlSdkVersionNumber); // 数字版本号:1.200000
    NSLog(@"字符数组版本号:%s", KJTUrlSdkVersionString); // 字符数组版本号:@(#)PROGRAM:KJTUrlSdk  PROJECT:KJTUrlSdk-1.2.3.4

如何生成Release模式的framework?

  • 一般的scheme,都是Run的时候Debug,Archive的时候Release。这个设定对于可执行文件是可行的,但是对于framework就不合适了。因为framework无法单独执行,没法Archive

  • 可以将frameworkRun改为Release。就算这样,用断点调试,也是可以停住的,不影响调试效果。可以这样说,Debug模式对于framework来说是没有意义的,统一使用Release就好了。

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容