如何在 SwiftUI 项目中使用 SwiftyDropbox API 进行身份验证?

问题描述 投票:0回答:2

一段时间以来,我一直在尝试寻找在 SwiftUI 项目中使用 SwiftyDropbox SDK 来验证 Dropbox 的解决方案,但这没有成功。

自述文件中提供的说明使用 AppDelegate 和 SceneDelegate。据我了解,后者对于 SwiftUI 来说是不可能的。我已经能够启动 OAuth2 Safari 窗口,但 DropboxClientsManager.authorizedClient 始终为零。

swift swiftui dropbox dropbox-sdk
2个回答
5
投票

我终于想通了。

按照 SwiftyDropbox 自述文件的说明设置 info.plist。

// <app_name>.swift

import SwiftUI
import SwiftyDropbox

@main
struct DropboxTestApp: App {

    init() {
        DropboxClientsManager.setupWithAppKey("<app key>")
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
// ContentView.swift

import SwiftUI
import SwiftyDropbox

struct ContentView: View {
    
    @State var isShown = false
    
    var body: some View {
        VStack {
            
            Button(action: {
                self.isShown.toggle()
            }) {
                Text("Login to Dropbox")
            }

            DropboxView(isShown: $isShown)
            
            Button {
                if let client = DropboxClientsManager.authorizedClient {
                    print("successful login")
                } else {
                    print("Error")
                }
            } label: {
                Text("Test Login")
            }
            
        }
        .onOpenURL { url in
            let oauthCompletion: DropboxOAuthCompletion = {
                if let authResult = $0 {
                    switch authResult {
                    case .success:
                        print("Success! User is logged into DropboxClientsManager.")
                    case .cancel:
                        print("Authorization flow was manually canceled by user!")
                    case .error(_, let description):
                        print("Error: \(String(describing: description))")
                    }
                }
            }
            DropboxClientsManager.handleRedirectURL(url, completion: oauthCompletion)
        }
    }
}

struct DropboxView: UIViewControllerRepresentable {
    typealias UIViewControllerType = UIViewController
    
    @Binding var isShown : Bool
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        
        if isShown {
            let scopeRequest = ScopeRequest(scopeType: .user, scopes: ["account_info.read", "files.metadata.write", "files.metadata.read", "files.content.write", "files.content.read"], includeGrantedScopes: false)
            DropboxClientsManager.authorizeFromControllerV2(
                UIApplication.shared,
                controller: uiViewController,
                loadingStatusDelegate: nil,
                openURL: { (url: URL) -> Void in UIApplication.shared.open(url, options: [:], completionHandler: nil) },
                scopeRequest: scopeRequest)
        }
    }
    
    func makeUIViewController(context _: Self.Context) -> UIViewController {
        return UIViewController()
    }
}

您不需要创建 AppDelegate。

我希望有人会发现这很有用。


0
投票

此替代解决方案不需要创建 DropboxView,尽管其工作原理完全相同(在新窗口中打开登录流程)。对于对 DropboxClientsManager.setupWithAppKey 的调用,我已将 AppDelegate 添加到 SwiftUI 项目中,并且还通过 Brierfly 测试将其添加到 .active scenePhase 的 .onChange(of: scenePhase) 中,并且似乎也有效。

struct ContentView: View {
    
    var body: some View {
        VStack {
            Spacer()

            Button("Login with Dropbox") {
                performLogin()
            }
            
            Spacer()
            Spacer()
        }
        .padding()
        .onOpenURL { url in
            print("url: \(url)")
            let oauthCompletion: DropboxOAuthCompletion = {
                if let authResult = $0 {
                    switch authResult {
                    case .success:
                        print("Success! User is logged into DropboxClientsManager.")
                    case .cancel:
                        print("Authorization flow was manually canceled by user!")
                    case .error(_, let description):
                        print("Error: \(String(describing: description))")
                    }
                }
            }
            DropboxClientsManager.handleRedirectURL(url, backgroundSessionIdentifier: "patata", completion: oauthCompletion)
        }
    }
    
    func performLogin() {
        let scopeRequest = ScopeRequest(scopeType: .user, scopes: ["account_info.read", "files.metadata.write", "files.metadata.read", "files.content.write", "files.content.read"], includeGrantedScopes: false)
        DropboxClientsManager.authorizeFromControllerV2(
            UIApplication.shared,
            controller: nil,
            loadingStatusDelegate: nil,
            openURL: { (url: URL) -> Void in UIApplication.shared.open(url, options: [:], completionHandler: nil) },
            scopeRequest: scopeRequest
        )
    }
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.