95 lines
3.1 KiB
Swift
95 lines
3.1 KiB
Swift
import SwiftUI
|
|
import AuthenticationServices
|
|
import CryptoKit
|
|
|
|
/// 自定义的 Apple 登录按钮组件
|
|
struct AppleSignInButton: View {
|
|
// MARK: - 属性
|
|
|
|
/// 授权请求回调
|
|
let onRequest: (ASAuthorizationAppleIDRequest) -> Void
|
|
|
|
/// 授权完成回调
|
|
let onCompletion: (Result<ASAuthorization, Error>) -> Void
|
|
|
|
/// 按钮文字
|
|
let buttonText: String
|
|
|
|
// MARK: - 初始化方法
|
|
|
|
init(buttonText: String = "Continue with Apple",
|
|
onRequest: @escaping (ASAuthorizationAppleIDRequest) -> Void,
|
|
onCompletion: @escaping (Result<ASAuthorization, Error>) -> Void) {
|
|
self.buttonText = buttonText
|
|
self.onRequest = onRequest
|
|
self.onCompletion = onCompletion
|
|
}
|
|
|
|
// MARK: - 视图主体
|
|
|
|
var body: some View {
|
|
Button(action: handleSignIn) {
|
|
HStack(alignment: .center, spacing: 8) {
|
|
Image(systemName: "applelogo")
|
|
.font(.system(size: 20, weight: .regular))
|
|
Text(buttonText)
|
|
.font(.system(size: 18, weight: .regular))
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.frame(height: 60)
|
|
.background(Color.white)
|
|
.foregroundColor(.black)
|
|
.cornerRadius(30)
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 30)
|
|
.stroke(Color.black, lineWidth: 1) // 使用黑色边框
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - 私有方法
|
|
|
|
private func handleSignIn() {
|
|
let provider = ASAuthorizationAppleIDProvider()
|
|
let request = provider.createRequest()
|
|
request.requestedScopes = [.fullName, .email]
|
|
|
|
// 创建 nonce 用于安全验证
|
|
let nonce = String.randomURLSafeString(length: 32)
|
|
request.nonce = sha256(nonce)
|
|
|
|
// 调用请求回调
|
|
onRequest(request)
|
|
|
|
// 创建并显示授权控制器
|
|
let controller = ASAuthorizationController(authorizationRequests: [request])
|
|
controller.delegate = Coordinator(onCompletion: onCompletion)
|
|
controller.performRequests()
|
|
}
|
|
|
|
private func sha256(_ input: String) -> String {
|
|
let inputData = Data(input.utf8)
|
|
let hashedData = SHA256.hash(data: inputData)
|
|
return hashedData.compactMap { String(format: "%02x", $0) }.joined()
|
|
}
|
|
|
|
// MARK: - 协调器
|
|
|
|
private class Coordinator: NSObject, ASAuthorizationControllerDelegate {
|
|
let onCompletion: (Result<ASAuthorization, Error>) -> Void
|
|
|
|
init(onCompletion: @escaping (Result<ASAuthorization, Error>) -> Void) {
|
|
self.onCompletion = onCompletion
|
|
}
|
|
|
|
// 授权成功回调
|
|
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
|
|
onCompletion(.success(authorization))
|
|
}
|
|
|
|
// 授权失败回调
|
|
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
|
|
onCompletion(.failure(error))
|
|
}
|
|
}
|
|
} |