티스토리 뷰
SwiftUI에서 구글로그인 띄우기
구글 로그인은 API로 제공되며 UIKit 프레임워크에서 쉽게 작동시킬 수 있도록 설계되어 있다. 이제 SwiftUI가 점점 보편화 됨에 따라 API도 전환이 되겠지만 현재까지는 업데이트 되지 않은 상황이라 방법을 공유하고자 한다.
구글 로그인 화면 띄우기
구글 로그인은 로그인 뷰를 띄울 뷰 컨트롤러를 제공해주어야 한다.
signIn(with: GIDConfiguration, presenting: UIViewController, callback: GIDSignInCallback?)
아무 뷰 컨트롤러나 제공한다고 해서 표시되는 것이 아니고 반드시 현재 화면에 띄워져 있어야 하고 다른 뷰 컨트롤러를 프레젠트 할 수 있어야 한다. 그렇기 때문에 SwiftUI와 같이 현재 뷰컨트롤러에 바로 접근이 불가능할 경우, 표시중인 UIWindow의 rootViewController를 제공하여야 한다.
UIWindow가 하나뿐인 경우 강제로 가져올 수 있는 방법이 있다.
guard let presentingViewController = (
UIApplication.shared.connectedScenes.first as? UIWindowScene
)?.windows.first?.rootViewController else {
fatalError()
}
이 방법의 경우 아이폰의 경우 문제가 없지만 아이패드의 경우 여러 윈도우를 띄우고 있을 수 있어 예상치 못한 동작이 나타날 수 있다. 그리고 보기에도 좋지 않다.
SwiftUI에서 사용중인 UIWindow 가져오기
현재 뷰의 맨 뒤에 빈 뷰를 삽입하여 해당 빈 뷰의 현재 UIWindow를 가져와 사용할 수 있다.
먼저 구글 로그인을 표시할 객체를 표현하는 GoogleSignInPresentaionContextProviding 프로토콜을 작성한다.
public protocol GoogleSignInPresentaionContextProviding: AnyObject {
func presentationAnchor() -> UIWindow
}
이 프로토콜은 구글 로그인을 처리하는 객체에서 프로퍼티로 보유하게 된다.
final class GoogleAuthManager {
weak var presentationContextProvider: GoogleSignInPresentaionContextProviding?
}
GoogleSignInPresentaionContextProviding 프로토콜을 따르는 UIView 객체를 만든다.
class ContextProvidingView: UIView, GoogleSignInPresentaionContextProviding {
func presentationAnchor() -> UIWindow {
guard let window = window else {
fatalError("UIWindow를 찾을 수 없음")
}
return window
}
}
ContextProvidingView를 SwiftUI에서 표시하기 위해 UIViewRepresentable로 감싼다.
struct PresentationContextProviderView: UIViewRepresentable {
func makeUIView(context: Context) -> ContextProvidingView {
return ContextProvidingView()
}
func updateUIView(_ uiView: ContextProvidingView, context: Context) {}
}
이제 이 뷰를 최상위뷰의 뒤에 삽입하여 UIWindow를 가져올 수 있도록 할 것이다. ZStack을 사용하여 ContentView의 뒤에 배치할 수 있다.
@main
struct DoongsterApp: App {
var body: some Scene {
WindowGroup {
ZStack {
PresentationContextProviderView()
ContentView()
}
}
}
}
최상위뷰에 PresentationContextProviderView를 삽입하는것 까지는 완료되었으니 이제 로그인 처리 객체에 GoogleSignInPresentaionContextProviding를 제공해주어야 한다. 이를 위해 클로저를 통해 ContextProvidingView를 전달할 수 있도록 변경할 것이다.
로그인 처리 객체에 ContextProvidingView 전달하기
ContextProvidingView의 이니셜라이저로 클로저를 전달받고 ContextProvidingView 자기 자신을 넘겨주도록 한다.
class ContextProvidingView: UIView, GoogleSignInPresentaionContextProviding {
init(onProviderCreated: (GoogleSignInPresentaionContextProviding) -> Void) {
super.init(frame: .zero)
onProviderCreated(self)
}
}
ContextProvidingView를 감싼 PresentationContextProviderView에 클로저를 저장한다.
struct PresentationContextProviderView: UIViewRepresentable {
var onProviderCreated: (GoogleSignInPresentaionContextProviding) -> Void
}
이제 최상위 뷰에서 클로저를 통해 로그인 처리 객체에 (PresentationContextProviding 프로토콜을 준수하는) ContextProvidingView를 전달하면 된다.
@main
struct DoongsterApp: App {
@StateObject var googleLoginManager = GoogleLoginManager()
var body: some Scene {
WindowGroup {
ZStack {
PresentationContextProviderView { provider in
googleLoginManager.presentationContextProvider = provider
}
ContentView()
}
}
}
}
뷰 모디파이어 + 뷰 익스텐션을 사용하여 아래와 같은 문법으로 제작하여 사용하면 더욱 직관적이고 편리하다. ZStack도 없앨 수 있고 어떤 역할을 하는지도 명확하게 보인다.
ContentView()
.googleLoginManagerPresentationContext { provider in
googleLoginManager.presentationContextProvider = provider
}'가이드' 카테고리의 다른 글
| 네이버 지도 SDK 줌 레벨 알아보기 (0) | 2022.07.30 |
|---|---|
| SwiftUI에서 뷰 스크린샷 캡쳐하기 (0) | 2022.07.30 |
| SwiftUI 프로젝트에서 커스텀 Scheme 또는 파일 연결 처리하기 (0) | 2022.04.13 |
| SwiftUI 커스텀 바인딩 활용하기 (0) | 2022.04.13 |
| SwiftUI fileImporter 파일선택기 사용하기 (UIDocumentPicker) (0) | 2022.04.12 |
