swift - 我可以将 Snapchat SDK (SnapKit) 与 SwiftUI 一起使用吗?

标签 swift swiftui snapchat uiviewrepresentable

我正在尝试集成 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 时提出的以下问题/观察:

  • 正如您正确意识到的那样,最基本的问题是 SCSDKLoginKit 模块已过时。 SCSDKLoginClient.login() 要求调用 View 符合 (UIKIT) UIViewController 类。所以我们必须使用带有 UIViewControllerRepresentable 的解决方法来充当我们的 SwiftUI <-> UIKit 中介。
  • 然而,根本问题与 SnapKit SDK 文档尚未更新以向开发人员提供 Snapchat Auth 和您的应用程序逻辑之间的 SceneDelegate 链接这一事实有关。因此,即使您正确实现了 SCSDKLoginButton,也并非一帆风顺!

  • 现在直接回答您的问题,您正在尝试将 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 会返回用户数据,但您的应用程序永远不会检索它。

    【前进】
  • SnapKitSDK(当前版本 1.4.3)需要与文档一起更新。
  • 我刚刚向 Snapchat 提交了一个支持问题,询问此更新何时发布,所以如果我听到更多消息,我会更新此内容。抱歉,如果您正在寻找 SCSDKLoginButton() 问题的直接解决方案,我只是想让您知道在当前时刻之外还有哪些挑战。

  • [延伸阅读]
  • Facebook 已经更新了他们的工具和文档以合并场景/应用程序代表。请参阅此处的步骤“5. 连接您的 App Delegate 和 Scene Delegate”:https://developers.facebook.com/docs/facebook-login/ios/
  • 关于swift - 我可以将 Snapchat SDK (SnapKit) 与 SwiftUI 一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61145929/

    相关文章:

    ios - 如何在没有 ViewControllers 的情况下使用 SwiftUI 获取当前位置?

    ios - Snap Kit 不使用 startSending 打开 Snapchat

    ios - 应用程序/后端架构 : How do Snapchat stories load so fast?

    Swift 覆盖子类的所有 setter 和 getter

    ios - 如何识别 UITabBarController 跟随哪个 "relationship"?

    swift - 将当天的日期保存在标签中

    swiftui - 当嵌入到 NavigationView SwiftUI 时,使列表部分在 SwiftUI 中不可折叠

    ios - 找到运动方向?

    swift - SwiftUI添加倒立面膜

    oauth-2.0 - Snapchat 登录工具包错误 : Missing PKCE parameters