微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 .sheet (SwiftUI) 上使用带有苹果的标志

如何解决在 .sheet (SwiftUI) 上使用带有苹果的标志

我所有的登录方法(如 fb 和 google 登录)都有协调器类并在 .sheet 上工作。 我试图从 this video 对这个视图做出同样的处理,但我被卡住了,根本找不到解决方案。我需要这个来从其他视图传递变量。

struct SignInWithAppleView: View {     
        @Environment (\.presentationMode) var presentationMode
        @State var coordinator: signInWithAppleCoordinator?
        var body: some View {
            vstack {
                SignInWithAppleButton()
                    .frame(height: 45)
                    .padding(.horizontal)
                    .onTapGesture {
                        self.coordinator = signInWithAppleCoordinator()
                        if let coordinator = self.coordinator {
                            coordinator.startSignInWithAppleFlow {
                                print("You successfuly signed in with apple")
                                self.presentationMode.wrappedValue.dismiss()
                            }
                        }
                    }
            }
        }
    }

我的谷歌登录代码示例如下

import SwiftUI
import GoogleSignIn
import Firebase

struct GoogleAuthView: UIViewRepresentable {
    
    @Binding var showAnimation: Bool
    @Binding var showSheet: Bool
    
    
    init(showAnimation: Binding<Bool>,showSheet: Binding<Bool>) {
        self._showAnimation = showAnimation
        self._showSheet = showSheet
    }
    
    func makeCoordinator() -> GoogleAuthView.Coordinator {
        return GoogleAuthView.Coordinator(showAnimation: self.$showAnimation,showSheet: self.$showSheet)
    }
    
    class Coordinator: NSObject,GIDSignInDelegate {
        
        @Binding var showAnimation: Bool
        @Binding var showSheet: Bool
        
        init(showAnimation: Binding<Bool>,showSheet: Binding<Bool>) {
            self._showAnimation = showAnimation
            self._showSheet = showSheet
        }
        
        
        
        func sign(_ signIn: GIDSignIn!,didSignInFor user: GIDGoogleUser!,withError error: Error?) {
            if let error = error {
                print(error.localizedDescription)
                return
            }
            
            guard let authentication = user.authentication else {
                return
                
            }
            self.showAnimation = true
            self.showSheet = false
            let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,accesstoken: authentication.accesstoken)
            Auth.auth().signIn(with: credential) { (authResult,error) in
                if let error = error,(error as NSError).code == AuthErrorCode.credentialAlreadyInUse.rawValue {
                    Auth.auth().signIn(with: credential) { result,error in
                        // continue
                        print("signIn result: " + authResult!.user.email!)
                        if let token = firebaseRegistrationPushToken {
                            checkUserAuthSettings(pushToken: token)
                        }
                    }
                } else {
                    // continue
                    print("Facebook Sign In")
                    if let token = firebaseRegistrationPushToken {
                        checkUserAuthSettings(pushToken: token)
                    }
                }

            }
            
        }
    }
    
    func makeUIView(context: UIViewRepresentableContext<GoogleAuthView>) -> GIDSignInButton {
        let view = GIDSignInButton()
        GIDSignIn.sharedInstance().delegate = context.coordinator
        GIDSignIn.sharedInstance()?.presentingViewController = UIApplication.shared.windows.last?.rootViewController
        return view
    }
    
    func updateUIView(_ uiView: GIDSignInButton,context: UIViewRepresentableContext<GoogleAuthView>) { }
}

苹果登录视频的完整代码

import Foundation
import SwiftUI
import AuthenticationServices
import CryptoKit
import Firebase

struct SignInWithAppleButton: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
        return ASAuthorizationAppleIDButton(type: .signIn,style: .black)
    }
    
    func updateUIView(_ uiView: ASAuthorizationAppleIDButton,context: Context) {
    }
}


class signInWithAppleCoordinator:NSObject,ASAuthorizationControllerPresentationContextProviding {
    
    private var onSignedIn: (() -> Void)?
    
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return UIApplication.shared.windows.first!
    }
    

    // Unhashed nonce.
    fileprivate var currentNonce: String?

    @available(iOS 13,*)
    func startSignInWithAppleFlow(onSignedIn:@escaping() ->Void ) {
        self.onSignedIn = onSignedIn
      let nonce = randomNonceString()
      currentNonce = nonce
      let appleIDProvider = ASAuthorizationAppleIDProvider()
      let request = appleIDProvider.createRequest()
      request.requestedScopes = [.fullName,.email]
      request.nonce = sha256(nonce)

      let authorizationController = ASAuthorizationController(authorizationRequests: [request])
      authorizationController.delegate = self
      authorizationController.presentationContextProvider = self
      authorizationController.performRequests()
    }

    @available(iOS 13,*)
    private func sha256(_ input: String) -> String {
      let inputData = Data(input.utf8)
      let hashedData = SHA256.hash(data: inputData)
      let hashString = hashedData.compactMap {
        return String(format: "%02x",$0)
      }.joined()

      return hashString
    }
}

@available(iOS 13.0,*)
extension signInWithAppleCoordinator: ASAuthorizationControllerDelegate {

  func authorizationController(controller: ASAuthorizationController,didCompleteWithAuthorization authorization: ASAuthorization) {
    if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
      guard let nonce = currentNonce else {
        fatalError("Invalid state: A login callback was received,but no login request was sent.")
      }
      guard let appleIDToken = appleIDCredential.identityToken else {
        print("Unable to fetch identity token")
        return
      }
      guard let idTokenString = String(data: appleIDToken,encoding: .utf8) else {
        print("Unable to serialize token string from data: \(appleIDToken.debugDescription)")
        return
      }
      // Initialize a Firebase credential.
        
      let credential = OAuthProvider.credential(withProviderID: "apple.com",idToken: idTokenString,rawNonce: nonce)
        Auth.auth().currentUser?.link(with: credential,completion: { (authresult,error) in
            //фиксируем ошибку при заходе с разных поставщиков на тот же ящик
            if let error = error,(error as NSError).code == AuthErrorCode.credentialAlreadyInUse.rawValue {
                print("The user you're trying to sign in with has already been linked")
                if let updatedCredential = (error as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as? OAuthCredential {
                    print("Signing in with using updating credentials")
                    Auth.auth().signIn(with: updatedCredential) { (authResult,error) in
                        if let user = authResult?.user {
                            if let callback = self.onSignedIn {
                                callback()
                            }
                            
                        }
                    }
                }
            }
            else {
                if let callback = self.onSignedIn {
                    callback()
                }
            }
        })
    }
  }

  func authorizationController(controller: ASAuthorizationController,didCompleteWithError error: Error) {
    // Handle error.
    print("Sign in with Apple errored: \(error)")
  }

}

// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
private func randomNonceString(length: Int = 32) -> String {
  precondition(length > 0)
  let charset: Array<Character> =
      Array("0123456789ABCDEFGHIJKLMnopQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
  var result = ""
  var remainingLength = length

  while remainingLength > 0 {
    let randoms: [UInt8] = (0 ..< 16).map { _ in
      var random: UInt8 = 0
      let errorCode = SecRandomcopyBytes(kSecRandomDefault,1,&random)
      if errorCode != errSecSuccess {
        fatalError("Unable to generate nonce. SecRandomcopyBytes Failed with Osstatus \(errorCode)")
      }
      return random
    }

    randoms.forEach { random in
      if remainingLength == 0 {
        return
      }

      if random < charset.count {
        result.append(charset[Int(random)])
        remainingLength -= 1
      }
    }
  }

  return result
}

struct SignInWithAppleView: View {
    @EnvironmentObject var session: SessionStore
    
    @Environment (\.presentationMode) var presentationMode
    @State var coordinator: signInWithAppleCoordinator?
    var body: some View {
        vstack {
            SignInWithAppleButton()
                .frame(height: 45)
                .padding(.horizontal)
                .onTapGesture {
                    self.coordinator = signInWithAppleCoordinator()
                    if let coordinator = self.coordinator {
                        coordinator.startSignInWithAppleFlow {
                            print("You successfuly signed in with apple")
                            self.presentationMode.wrappedValue.dismiss()
                        }
                    }
                }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。