728x90
728x90
SMALL
저번에 구글로그인 구현하는 글을 작성했는데,
해당 방법은 스토리보드(StoryBoard)를 사용한 방법이었다.
오늘은 SwiftUI를 사용해서 구글 로그인을 진행할 예정이며,
코드 구현 전 기본 세팅은 방법이 동일하기에 이전 글을 참고 하면 된다 :)
사전 세팅 방법
결과화면
Document
Github
사전세팅 차이점
pod 'GoogleSignInSwiftSupport'
기존에는 'GoogleSignIn'만 다운하였으나 SwiftUI를 사용할 경우에는 'Google 계정으로 로그인' 버튼의 확장 프로그램인 'GoogleSignInSwiftSupport'도 추가해준다
구현하기
- Main.swift
@main
struct SocialLoginUIApp: App {
var body: some Scene {
WindowGroup {
ContentView(userData: UserData(url: nil, name: "", email: ""))
.onOpenURL { url in
GIDSignIn.sharedInstance.handle(url)
}
}
}
}
App 프로토콜을 채택하는 메인 Swift 파일에 GIDSignIn의 handleURL를 호출한다
- UserData.swift
struct UserData {
let url:URL?
let name:String
let email:String
init(url: URL?, name: String, email: String) {
self.url = url
self.name = name
self.email = email
}
}
유저 정보를 담는 구조체로 url은 프로필 이미지 주소이다
- ContentView.swift
struct ContentView: View {
// 로그인 상태
@State private var isLogined = false
// 유저 데이터
@State private var userData:UserData
// 팝업용
@State private var isAlert = false
public init(isLogined: Bool = false, userData: UserData) {
_isLogined = State(initialValue: isLogined)
_userData = State(initialValue: userData)
}
var body: some View {
NavigationStack {
ZStack {
GoogleSignInButton(
scheme: .light,
style: .wide,
action: {
googleLogin()
})
.frame(width: 300, height: 60, alignment: .center)
}
.navigationDestination(isPresented: $isLogined, destination: { MyPageView(userData: $userData) })
}
.onAppear(perform: {
// 로그인 상태 체크
checkState()
})
.alert(LocalizedStringKey("로그인 실패"), isPresented: $isAlert) {
Text("확인")
} message: {
Text("다시 시도해주세요")
}
}
}
메인 로그인 화면
- isLogined : 로그인 상태 체크를 위한 변수(T-로그인, F-로그아웃)
- isAlert : 팝업 호출 여부를 확인하기 위한 변수(T-팝업 열림, F-팝업 닫힘)
- GoogleSignInButton() : 구글에서 제공된 로그인 버튼
- NavigationStack, navigationDestination : 마이페이지로 이동을 위한 네비게이션
- onAppear() : 화면이 보여질 때 수행할 내용
- alert() : 로그인 실패 시, 팝업 호출
{
// 상태 체크
func checkState() {
GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
if error != nil || user == nil {
// 로그아웃 상태
print("Not Sign In")
} else {
// 로그인 상태
guard let profile = user?.profile else { return }
let data = UserData(url: profile.imageURL(withDimension: 180), name: profile.name, email: profile.email)
userData = data
isLogined = true
print(isLogined)
}
}
}
// 구글 로그인
func googleLogin() {
// rootViewController
guard let presentingViewController = (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first?.rootViewController else { return }
// 로그인 진행
GIDSignIn.sharedInstance.signIn(withPresenting: presentingViewController) { signInResult, error in
guard let result = signInResult else {
isAlert = true
return
}
guard let profile = result.user.profile else { return }
let data = UserData(url: profile.imageURL(withDimension: 180), name: profile.name, email: profile.email)
userData = data
isLogined = true
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(userData: UserData(url: nil, name: "", email: ""))
}
}
- checkState() : 로그인 여부를 체크하여 isLogined를 변경하고 유저 정보를 저장함
- googleLogin() : 구글 로그인을 진행하고 유저 정보를 저장함
- MyPageView.swift
struct MyPageView: View {
// 화면 종료
@Environment(\.dismiss) private var dismiss
// 유저 데이터 바인딩
@Binding var userData:UserData
var body: some View {
VStack (spacing: 30) {
// 프로필
AsyncImage(url: userData.url)
.imageScale(.small)
.frame(width: 180, height: 180, alignment: .center)
.padding(EdgeInsets(top: 60, leading: 0, bottom: 0, trailing: 0))
// 이름
Text(userData.name)
// 이메일
Text(userData.email)
Spacer()
HStack {
// 로그아웃 버튼
Button {
logout()
} label: {
Text("로그아웃")
}
.frame(width: 60, height: 33, alignment: .bottom)
.padding(EdgeInsets(top: 0, leading: 30, bottom: 30, trailing: 0))
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
// 뒤로 가기 버튼 숨김
.navigationBarBackButtonHidden(true)
}
// 로그아웃
func logout() {
GIDSignIn.sharedInstance.signOut()
// 메인으로 돌아가기
dismiss()
}
}
struct MyPageView_Previews: PreviewProvider {
static var previews: some View {
MyPageView(userData: .constant(UserData(url: nil, name: "이름", email: "이메일")))
}
}
마이페이지 화면
- dismiss() : 현재 화면을 닫음
- logout() : 로그아웃 후 메인으로 돌아감
다음번엔 애플, 카카오 로그인을 진행해서 포스팅하고자 한다.
SwiftUI 연습을 위해 앞으로 기능 구현과 같은 간단한 내용의 포스팅은 SwiftUI로 제작하여 진행하려한다.
이렇게 하면 조금은 더 빨리 익숙해질 수 있지 않을까... ㅜㅜ
728x90
728x90
LIST