由于目前行业的变化,移动端的开发早已没有铮铮日上的景象了,作为iOS和Android的双料开发,这一现象表现得更为明显。目前在社交网络上已经很少人去分享移动开发的文章和开源库了,新出版的书也是寥寥无几。最近新项目需要开发iOS移动端应用,我发现写个应用需要更仔细地了解技术的实现细节,从搜索引擎中抽丝拨茧,才能理清楚实现方法。
今天就总结下一个基础的功能之一,那就是微信登录。如果你碰巧是iOS新手或者在做闲余项目,可以参考下我的记录,少踩一些坑。
准备工作
我默认你是用Swift开发应用,用Cocoapods管理依赖。还需要准备一些基础的信息:
引入微信SDK
首先打开微信的SDK更新日志,可以看到SDK的更新列表,目前最新的版本是2.0.5。目前有几种可选形式:
- 下载.a静态资源包(5.9MB)
- 下载.a静态资源包,无支付(5.8MB)
- 下载XCFramework形式资源包(4.4MB)
- 下载XCFramework形式资源包,无支付(4.3MB)
- 通过CocoaPods安装静态库
- 通过CocoaPods安装XCFramework
刚开始我奇怪的是,通过CocoaPods安装的时候,没有无支付版本。后来下载资源包下来之后,发现大小也没差多少,其实无所谓了。鉴于CocoaPods使用更方便,配置更简单,直接在Podfile中添加语句:
pod 'WechatOpenSDK-XCFramework'
注意CocoaPods仓库还有个微信官方的依赖叫做WechatOpenSDK(微信官方依赖就这两个,辛苦我翻了半天CocoaPods的官方Spec仓库),它仅仅适用于OC语言项目。如果要在Swift语言中调用它,你还需要创建桥接头文件,才可以让Swfit语言识别并使用依赖。
然后再在命令行中执行命令安装依赖:
pod install
如果后续SDK版本有更新,可以通过命令更新:
pod update
至此,你就可以在代码里引入import WechatOpenSDK并使用库中的类了。
配置微信SDK
配置主要是为了方便在App和微信之间来回跳转。
首先需要配置Info.plist中的LSApplicationQueriesSchemes,它是iOS的隐私安全白名单,只有配置了它,才可以通过canOpenURL方法检测某些应用是否安装(注意这只是限制查询,不限制打开)。微信的scheme有3个,需要把它们全部配置进去。
其次需要配置Info.plist中的CFBundleURLTypes,它是告诉系统,App本身能响应哪些scheme。这个是为了方便微信能跳转回来,微信和我们约定的scheme就是开放平台的App ID。从微信跳转回来的时候,微信可能会带回一些额外信息,这个SDK会读取一些信息比如登录信息和支付信息等,这个我们下面会提到。
你可以参考为微信的官方配置文档,其中4.1.3和4.1.4部分的图片说明了在Xcode哪个地方配置。为了更方便你确认自己的配置是否成功,我给你Info.plist会发生的变化,这样方便你在用git的时候做对比:
<!-- 头部 -->
<dict>
<!-- 其他配置 -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
<string>weixinULAPI</string>
<string>weixinURLParamsAPI</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>weixin</string>
<key>CFBundleURLSchemes</key>
<array>
<string>微信开放平台上应用的App ID</string>
</array>
</dict>
</array>
<!-- 其他配置 -->
</dict>
运行微信SDK
和很多的工具SDK一样,微信的SDK同样需要在AppDelegate中对SDK进行初始化:
// 添加微信SDK日志,根据具体情况添加
WXApi.startLog(by: WXLogLevel.detail) { s in print(s)}
// 注册APP信息
WXApi.registerApp(APP_ID, universalLink: UNIVERSAL_LINK)
跳转微信
用户点击你应用里的微信登录之后,可以调用以下方法,就跳到微信了:
func sendWechatLoginRequest() {
let req = SendAuthReq()
req.scope = "snsapi_userinfo"
req.state = "[按需传递]";
WXApi.send(req)
}
跳回应用
这一步就是比较烧脑了,因为它伴随着iOS历史API的变更,以及App跳转方式的变更。
当微信跳转回来的时候,按照我们之前编程经验来说,应该注册一个监听器来接收微信传递过来的信息。微信SDK定义的这样的类就是WXApiDelegate,它有一个onResp方法用于接收微信返回的响应,我们可以这样实现:
/// 微信跳转回来之后,回调此方法
func onResp(_ resp: BaseResp) {
guard let authResp = resp as? SendAuthResp else { return }
if (authResp.errCode == 0) {
let code = authResp.code
// 调用接口处理身份信息
} else {
// 微信登录失败
}
}
那么谁来实现这个接口,谁来调用呢?我们一步一步探索。
iOS最早的跨App调用方法,是使用URL Scheme。因为任何App都能处理相同的Scheme,导致安全性降低。所以在iOS 9之后,苹果引入了Universal Link。现在iOS已经到26版本了,微信和SDK都迭代了不知道多少个版本了,是不是就不用考虑URL Scheme的跳转方式了。我搜索了相关的信息,以及询问了ChatGPT,都是建议同时保留,那我们就同时支持吧。
假设AppDelegate实现了WXApiDelegate,可以实现以下方法来处理:
/// iOS 9引入,用它来处理Url Scheme
func application(_ app: UIApplication, open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return WXApi.handleOpen(url, delegate: self)
}
/// iOS 8引入,处理Unversal Link
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
return WXApi.handleOpenUniversalLink(userActivity, delegate: self)
}
处理了URL Scheme和Unversal Link的回调之后,应用就能正常处理微信的回调了。你可以观察到上面的方法都传入了delegate,这样onResp方法就能正常被调用到了。
需要额外说明的是,下面两个是已经废弃的方法,微信的文档和搜索引擎上的很多文章都可以看到。我在写代码的时候就非常疑惑,到底哪个方法是处理跳转的,我的头都大了。这下你可以省事儿了:
func application(_ application: UIApplication, handleOpen url: URL) -> Bool {...}
func application(_ application: UIApplication, open url: URL,
sourceApplication: String?, annotation: Any) -> Bool {...}
多场景支持
在iOS 13之后,苹果开始支持多场景 App,也就是应用可能有多个窗口,比如说在iPad上,应用是支持分屏的,左右两个屏幕可以是同一个应用窗口,为了处理每个窗口,也就是每个场景的事件,很多方法从AppDelegate移到了SceneDelegate。下面是SceneDelegate中的需要实现的相关代码:
/// 处理通过URL Scheme跳转过来的情况
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
WXApi.handleOpen(url, delegate: self)
}
/// 处理通过Universal Link跳转过来的情况
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
WXApi.handleOpenUniversalLink(userActivity, delegate: self)
}
对于目前的新的App开发场景,最低的iOS支持版本可能都在iOS 13以上了,那么其实只保留SceneDelegate中的代码就行了。AppDelegate中的大片代码就删掉了(除非你主动不支持多场景)。从此你就得到了最佳实践!
相关参考
最后修改于 2025-12-09