我正在尝试集成 Snapkit使用 iOS 应用程序,但我想使用 SwiftUI 而不是 UIKit。我已经使用 Snapkit 完成了所需的设置,现在我正在尝试让 snapchat 登录按钮显示在我的应用程序中。我知道 Snapkit SDK 是为 UIKit 而不是 SwiftUI 制作的,但 SwiftUI 有办法 wrap UIViews into SwiftUI使用 UIViewRepresentable 协议(protocol)。我试过实现这个,但登录按钮仍然不显示。
这是我的代码:
import SwiftUI
import UIKit
import SCSDKLoginKit
struct ContentView: View {
var body: some View {
SnapchatLoginButtonView()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct SnapchatLoginButtonView: UIViewRepresentable {
func makeCoordinator() -> Coordinator {
Coordinator()
}
func makeUIView(context: Context) -> SCSDKLoginButton {
let s = SCSDKLoginButton()
s.delegate = context.coordinator
return s
}
func updateUIView(_ uiView: SCSDKLoginButton, context: Context) {
}
class Coordinator: NSObject, SCSDKLoginButtonDelegate {
func loginButtonDidTap() {
}
}
}
我有一种感觉,我在 SCSDKLoginButton 中遗漏了一些东西,但不确定它是什么,所以这里是文件 SCSDKLoginButton.h 以供引用。任何帮助将不胜感激!
//
// SCSDKLoginButton.h
// SCSDKLoginKit
//
// Copyright © 2018 Snap, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol SCSDKLoginButtonDelegate
- (void)loginButtonDidTap;
@end
@interface SCSDKLoginButton : UIView
@property (nonatomic, weak, nullable) id<SCSDKLoginButtonDelegate> delegate;
- (instancetype)initWithCompletion:(nullable void (^)(BOOL success, NSError *error))completion NS_DESIGNATED_INITIALIZER;
@end
最佳答案
巧合的是,在您发布问题大约 3 天后,我尝试在一个专有的 SwiftUI/iOS13 项目中实现 SnapKit SDK。
不幸的是,我无法直接解决您的问题,因为 Snapchat 必须使用其 SDK 解决一些关键问题,然后才能使用 iOS 13 中引入的 SceneDelegate 和 AppDelegate Paradigm 进行开发。但我希望我能阐明您的问题提问并将我的发现展示给处于类似困境中的任何其他人。
这些是我在 SwiftUI 中实现 SCSDKLoginKit 和 SCSDKBitmojiKit 时提出的以下问题/观察:
现在直接回答您的问题,您正在尝试将 SCSDKLoginButton 包装在 UIViewControllerRepresentable 中,这是可以做到的,我相信比我自己更了解协调员等的人可以帮助您解决这个问题。但是,我只是想表明,在 snapchat 提供更新的 SDK 之前,您目前的努力可能会徒劳无功。
这是我的设置:
[内容 View .swift]
import SwiftUI
struct ContentView: View {
@State private var isPresented = false
var body: some View {
Button("Snapchat Login Button") { self.isPresented = true}
.sheet(isPresented: $isPresented) {
LoginCVWrapper()
}
}
}
[登录CVWrapper.swift]
import SwiftUI
import UIKit
import SCSDKLoginKit
struct LoginCVWrapper: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
return LoginViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
//Unused in demonstration
}
}
[LoginViewController.swift]
import UIKit
import SCSDKLoginKit
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
performLogin() //Attempt Snap Login Here
}
//Snapchat Credential Retrieval Fails Here
private func performLogin() {
//SCSDKLoginClient.login() never completes once scene becomes active again after Snapchat redirect back to this app.
SCSDKLoginClient.login(from: self, completion: { success, error in
if let error = error {
print("***ERROR LOC: manualTrigger() \(error.localizedDescription)***")
return
}
if success {
self.fetchSnapUserInfo({ (userEntity, error) in
print("***SUCCESS LOC: manualTrigger()***")
if let userEntity = userEntity {
DispatchQueue.main.async {
print("SUCCESS:\(userEntity)")
}
}
})
}
})
}
private func fetchSnapUserInfo(_ completion: @escaping ((UserEntity?, Error?) -> ())){
let graphQLQuery = "{me{displayName, bitmoji{avatar}}}"
SCSDKLoginClient
.fetchUserData(
withQuery: graphQLQuery,
variables: nil,
success: { userInfo in
if let userInfo = userInfo,
let data = try? JSONSerialization.data(withJSONObject: userInfo, options: .prettyPrinted),
let userEntity = try? JSONDecoder().decode(UserEntity.self, from: data) {
completion(userEntity, nil)
}
}) { (error, isUserLoggedOut) in
completion(nil, error)
}
}
}
[运行如下] :
GIF: Code Running On Device
有关 SceneDelegate 接口(interface)链接问题的更多信息:
当您不可避免地实现 SCSDKLoginClient.login() 调用时(大概是在按下您的 SCSDKLoginButton 时),Snapchat 将打开,假设您的应用程序已链接到 Snapchat 开发门户中,它将正确显示“授予访问权限”表。
当您接受这些权限时,Snapchat 会重定向到您的应用程序。然而,这就是您的应用程序与检索 snapchat 用户名/bitmoji 之间的链接将崩溃的地方。这是因为在新的 iOS 13 应用程序中,SceneDelegate 会在您的应用程序状态更改时处理,而不是像 iOS13 之前的版本那样处理 AppDelegate。因此 Snapchat 会返回用户数据,但您的应用程序永远不会检索它。
【前进】
[延伸阅读]
关于swift - 我可以将 Snapchat SDK (SnapKit) 与 SwiftUI 一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61145929/