AppleSignInWrapper 1.2

AppleSignInWrapper 1.2

Genaro Arvizu 维护。



Quality Gate Status

AppleSignInWrapper

实现 Apple 登录的简单方法

内容

  1. 功能
  2. 要求
  3. 安装
  4. UIKit 示例
  5. SwiftUI 示例
  6. 注意

功能

  • SwiftUI 中的 Apple 登录按钮!
  • Storyboard 中的 Apple 登录按钮!
    • 状态
    • 颜色
    • 宽度
  • Apple 登录功能的包装器

要求

  • iOS 9+ (类和协议在 iOS 13 中可用)
  • Swift 4+
  • 设置项目能力

安装

CocoaPods

在您的 podfile 中添加下一行

pod 'AppleSignInWrapper'

Swift Package Manager

在您的项目的 Swift Package 中添加以下 URL 并设置最后一个版本号

https://github.com/chibombo/AppleSignInWrapper

UIKit 示例

  • 如果存在,如何检查会话的 状态。《KeychainItem》用于在 Keychain 中获取和设置 appleId(不包括在包装器中)
import UIKit
import AuthenticationServices
import AppleSignInWrapper

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
        if #available(iOS 13.0, *) {
            AppleSignInWrapper().checkUserState(userID: KeychainItem.currentUserIdentifier) { (state: ASAuthorizationAppleIDProvider.CredentialState?, error:Error?) in
                if let anError: Error = error{                    
                    // Here you should call your Login ViewController
                } else if let aState: ASAuthorizationAppleIDProvider.CredentialState = state{
                    switch aState {
                    case .authorized:
                        DispatchQueue.main.async {
                            // Here you should call your backend to create a session
                        }
                    case .notFound, .revoked:
                        DispatchQueue.main.async {
                            // Here you should call your Login ViewController 
                        }
                    default:
                        // Here you should call your Login ViewController
                    }
                } else {
                    // Here you should call your Login ViewController
                }
            }
        } else {
            // Fallback on earlier versions
            // Here you should call your Login ViewController without Apple Sign In Button
        }
        return true
    }
  • 如何使用包装器实现 Apple Sign In
import UIKit
import AuthenticationServices
import AppleSignInWrapper

@available(iOS 13.0, *)
class ViewController: AppleIDLoginDelegate {
    // MARK: - Outlets

    @IBOutlet weak var btnAppleSignIn: AppleIDButtonWrapper!
    
    var appleWrapper: AppleSignInWrapper!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btnAppleSignIn.addTarget(self,
                                 action: #selector(userTappedSignInWithApple),
                                 for: .touchUpInside)
        appleWrapper = AppleSignInWrapper(view: self.view)
        appleWrapper.delegate = self
        // Do any additional setup after loading the view.
    }
    
    @objc func userTappedSignInWithApple() {
        appleWrapper.requestSignIn()
    }
    
    func appleSignInWrapper(didComplete withError: Error) {

    }
    
    func appleSignInWrapper(didComplete withUser: UserInformation) {
        // Here you should save your user identifier and backend stuff
         
    }
}
  • 如何在使用 Storyboard 中使用 AppleSignInButton
    • 在您的 Storyboard 中创建一个 UIButton
    • AppleIDButtonWrapper 设置为按钮的自定义类。
    • How to set AppleIDButtonWrapper
    • 享受并自定义您的按钮
    • How to set AppleIDButtonWrapper
    • How to set AppleIDButtonWrapper
    • How to set AppleIDButtonWrapper
    • 如果您使用约束,请阅读 Apple 指南以避免在约束中的警告,并使按钮正确地出现在您的视图中。

SwiftUI 示例

  • 创建一个用于使用 AppleIDButtonWrapperUIViewRepresentable
import SwiftUI
import AppleSignInWrapper

struct AppleSignInButton: UIViewRepresentable {
    
    @Binding var firstName: String
    @Binding var lastName: String
    @Binding var userIdentifier: String
    @Binding var email: String?
    
    typealias UIViewType = AppleIDButtonWrapper
    
    func makeCoordinator() -> AppleSignInCoordinator {
        return AppleSignInCoordinator(loginView: self)
    }

    func makeUIView(context: UIViewRepresentableContext<AppleSignInButton>) -> AppleIDButtonWrapper {
        let appleSignInButton = AppleIDButtonWrapper()
        appleSignInButton.authButtonType = 1
        appleSignInButton.authButtonStyle = 2
        appleSignInButton.layer.cornerRadius = 0
        appleSignInButton.addTarget(context.coordinator, action: #selector(context.coordinator.userTappedAppleSignIn), for: .touchUpInside)
        return appleSignInButton
    }

    func updateUIView(_ uiView: AppleIDButtonWrapper, context: UIViewRepresentableContext<AppleSignInButton>) {
    }
}
  • 创建一个 coordinator 来管理包装器的代理方法。
import SwiftUI
import AuthenticationServices
import AppleSignInWrapper

class AppleSignInCoordinator: NSObject {
    
    var appleWrapper: AppleSignInWrapper!
    var loginView: AppleSignInButton?

    override init() {
        super.init()
        appleWrapper = AppleSignInWrapper()
        appleWrapper.delegate = self
    }

    init(loginView: AppleSignInButton) {
        super.init()
        self.loginView = loginView
        appleWrapper = AppleSignInWrapper()
        appleWrapper.delegate = self
    }

    @objc func userTappedAppleSignIn() {
        appleWrapper.view = UIApplication.shared.windows.last!.rootViewController?.view
        appleWrapper.requestSignIn()
    }
}

extension AppleSignInCoordinator: AppleIDLoginDelegate {
    func appleSignInWrapper(didComplete withError: Error) {
        
    }
    
    func appleSignInWrapper(didComplete withUser: UserInformation, nonce: String?) {
        loginView?.email = withUser.email
        loginView?.firstName = withUser.firstName
        loginView?.lastName = withUser.lastName
        loginView?.userIdentifier = withUser.userIdentifier       
    }  
}
  • 使用您的 AppleSignInButton
import SwiftUI

struct ContentView: View {
    var body: some View {
        AppleSignInButton(firstName: .constant(""),
                          lastName: .constant(""),
                          userIdentifier: .constant(""),
                          email: .constant(""))
            .frame(width: 200, height: 40, alignment: .center)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

注释