如何在SwiftUI上登录Facebook?

16

目前没有很多关于在SwiftUI中使用Facebook登录的资源。我不确定我的代码是否需要ViewController,因为Facebook的LoginManager.login()含有一个ViewController参数-然而,这在SwiftUI中并没有很好的对应。

无论如何,当用户单击下面的Button时,我正在尝试将用户登录到Facebook:

LoginView.swift

import Foundation
import SwiftUI
import FBSDKLoginKit

struct LoginView: View {
    @EnvironmentObject var auth: UserAuth
    var body: some View {
        ZStack {
            VStack {
                Image("launcher_logo").resizable()
                .scaledToFit()
                .frame(height: 100)
                    .padding(.top, 100)
                Spacer()
                Button(action: {
                    FBLogin()
                }) {
                    Text("Continue with Facebook")
                }.foregroundColor(Color.black)

当点击按钮时,它会初始化下面的FBLogin,然后在其init()中触发login()函数。
class FBLogin: LoginManager {

    let loginButton = FBLoginButton()
    let token = AccessToken.current
    let permissions = ["user_birthday", "user_gender", "public_profile"]

    override init(){
        super.init()
        logIn(permissions: permissions, from: nil)
        print("fb init()")
    }

    override func logIn(permissions: [String], from fromViewController: UIViewController?, handler: LoginManagerLoginResultBlock? = nil) {
        // TODO
    }

}

不过我不确定接下来该怎么做。目前只有fb init()输出,但我想执行登录并监听登录结果。

有什么想法吗?


你可以使用UIViewControllerRepresentable来处理SwiftUI中的UIViewController相关内容。 - vincent
谢谢。UIViewControllerRepresentable能让我创建自定义按钮/样式吗? - Zorgan
2个回答

22

只需在ObservableObject中创建LoginManager实例,然后自定义登录完成即可。您可以轻松地在SwiftUI View内使用。无需UIViewControllerRepresentable。这是我的示例。

struct ContentView: View {
    @ObservedObject var fbmanager = UserLoginManager()
    var body: some View {
        Button(action: {
            self.fbmanager.facebookLogin()
        }) {
            Text("Continue with Facebook")
        }
    }
}

class UserLoginManager: ObservableObject {
    let loginManager = LoginManager()
    func facebookLogin() {
        loginManager.logIn(permissions: [.publicProfile, .email], viewController: nil) { loginResult in
            switch loginResult {
            case .failed(let error):
                print(error)
            case .cancelled:
                print("User cancelled login.")
            case .success(let grantedPermissions, let declinedPermissions, let accessToken):
                print("Logged in! \(grantedPermissions) \(declinedPermissions) \(accessToken)")
                GraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name"]).start(completionHandler: { (connection, result, error) -> Void in
                    if (error == nil){
                        let fbDetails = result as! NSDictionary
                        print(fbDetails)
                    }
                })
            }
        }
    }
}

1
如果您没有任何已发布的变量,为什么要将类声明为ObservableObject?我认为您需要一个存储Facebook登录是否成功的已发布变量。 - davidev
1
我希望Google能够更改其SDK,以与SwiftUI兼容。 - Dscyre Scotti
1
这段代码无法编译。logIn方法的闭包需要两个参数,而且你不能在loginResult上进行切换。 - Pigpocket
我对SwiftUI和Facebook SDK还比较新,但只要您导入FacebookLogin,它似乎可以正常工作。 - avivmg
根据@davidev的评论,我理解fbmanager应该用StateObject进行注释,而不是ObservableObject。后者适用于当对象由父视图拥有并作为参数传递给此视图时。 - realh
显示剩余2条评论

1

看一下使用 SwiftUI 的回调包装器,以便使用 Facebook 登录和 Graph API 请求:https://github.com/axmav/combine-extensions

LoginManager()
            .logIn(permissions: [.publicProfile, .email])
            .flatMap { loginResult -> AnyPublisher<Account?, Error> in
                switch loginResult {
                case .failed(let error):
                    return Fail(outputType: Account?.self, failure: error).eraseToAnyPublisher()
                case .cancelled:
                    return Just(Account?.none)
                        .setFailureType(to: Error.self)
                        .eraseToAnyPublisher()
                case .success(let grantedPermissions, let declinedPermissions, let accessToken):
                    return GraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name"])
                        .start(type: Account.self)
                }
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接