美文网首页综合
使用动态framework封装微信SDK实践2019-11-14

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

作者: 勇往直前888 | 来源:发表于2019-11-14 19:36 被阅读0次

需求

对外提供一个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

相关文章

网友评论

    本文标题:使用动态framework封装微信SDK实践2019-11-14

    本文链接:https://www.haomeiwen.com/subject/scnlictx.html