WebViewとは
WebView.swift
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let url: String
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
guard let url = URL(string: url) else {
return
}
let request = URLRequest(url: url)
uiView.load(request)
}
}
ContentView.swift
※コード全体の仕組みとしてはGoogleのログインが出来たらアカウントの情報やアイコンと一緒にWebViewも表示されるようになっています。
import SwiftUI
import Firebase
import FirebaseAuth
import GoogleSignIn
struct ContentView: View {
private let url = "https://www.apple.com"
@State private var isSignedIn = false
@State private var userName: String = ""
@State private var userEmail: String = ""
@State private var profileImage: UIImage? = nil
var body: some View {
VStack(spacing: 20) {
//MARK: - ログイン後
if isSignedIn {
VStack {
if let profileImage = profileImage {
Image(uiImage: profileImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.clipShape(Circle())
.overlay(Circle().stroke(Color.blue, lineWidth: 2))
.shadow(radius: 5)
}
Text("Welcome, \(userName)")
.font(.title2)
.bold()
Text(userEmail)
.font(.subheadline)
.foregroundColor(.gray)
Button("Sign Out") {
signOut()
}
.frame(width: 200, height: 50)
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(10)
WebView(url: url)//ログイン成功したらWebViewが表示される
}
} else {
VStack {
GoogleSignInButton {
signInWithGoogle()
}
}
}
}
.padding()
.onAppear {
restoreSession()
}
}
private func signInWithGoogle() {
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
let config = GIDConfiguration(clientID: clientID)
guard let rootViewController = UIApplication.shared.connectedScenes
.compactMap({ $0 as? UIWindowScene })
.flatMap({ $0.windows })
.first(where: { $0.isKeyWindow })?.rootViewController else {
print("Unable to get root view controller.")
return
}
GIDSignIn.sharedInstance.signIn(withPresenting: rootViewController) { result, error in
if let error = error {
print("Google Sign-In failed: \(error.localizedDescription)")
return
}
guard let user = result?.user,
let idToken = user.idToken?.tokenString else { return }
let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: user.accessToken.tokenString)
Auth.auth().signIn(with: credential) { authResult, error in
if let error = error {
print("Firebase Authentication failed: \(error.localizedDescription)")
} else {
self.isSignedIn = true
self.userName = user.profile?.name ?? "No Name"
self.userEmail = user.profile?.email ?? "No Email"
// Load profile image
if let imageURL = user.profile?.imageURL(withDimension: 200) {
loadProfileImage(from: imageURL)
saveSession(userName: self.userName, userEmail: self.userEmail, profileImageURL: imageURL)
}
}
}
}
}
private func signOut() {
do {
try Auth.auth().signOut()
GIDSignIn.sharedInstance.signOut()
clearSession()
self.isSignedIn = false
self.userName = ""
self.userEmail = ""
self.profileImage = nil
} catch {
print("Failed to sign out: \(error.localizedDescription)")
}
}
private func loadProfileImage(from url: URL) {
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error {
print("Failed to load profile image: \(error.localizedDescription)")
return
}
if let data = data, let image = UIImage(data: data) {
DispatchQueue.main.async {
self.profileImage = image
}
}
}.resume()
}
// MARK: - Session Management
private func saveSession(userName: String, userEmail: String, profileImageURL: URL) {
UserDefaults.standard.setValue(userName, forKey: "userName")
UserDefaults.standard.setValue(userEmail, forKey: "userEmail")
UserDefaults.standard.setValue(profileImageURL.absoluteString, forKey: "profileImageURL")
UserDefaults.standard.setValue(true, forKey: "isSignedIn")
}
private func restoreSession() {
let defaults = UserDefaults.standard
if defaults.bool(forKey: "isSignedIn") {
self.isSignedIn = true
self.userName = defaults.string(forKey: "userName") ?? ""
self.userEmail = defaults.string(forKey: "userEmail") ?? ""
if let imageURLString = defaults.string(forKey: "profileImageURL"),
let imageURL = URL(string: imageURLString) {
loadProfileImage(from: imageURL)
}
}
}
private func clearSession() {
let defaults = UserDefaults.standard
defaults.removeObject(forKey: "userName")
defaults.removeObject(forKey: "userEmail")
defaults.removeObject(forKey: "profileImageURL")
defaults.setValue(false, forKey: "isSignedIn")
}
}
// MARK: - Google Sign-In Button
struct GoogleSignInButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
HStack {
Image(systemName: "g.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.foregroundColor(.white)
Text("Sign in with Google")
.fontWeight(.semibold)
.font(.system(size: 18))
}
.frame(width: 250, height: 50)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(25)
}
.shadow(radius: 5)
}
}
#Preview {
ContentView()
}
WebViewを使用している箇所
if let profileImage = profileImage{ } の内部となっています
VStack {
if let profileImage = profileImage {
Image(uiImage: profileImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.clipShape(Circle())
.overlay(Circle().stroke(Color.blue, lineWidth: 2))
.shadow(radius: 5)
}
Text("Welcome, \(userName)")
.font(.title2)
.bold()
Text(userEmail)
.font(.subheadline)
.foregroundColor(.gray)
Button("Sign Out") {
signOut()
}
.frame(width: 200, height: 50)
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(10)
WebView(url: url)//ログイン成功したらWebViewが表示される
}
Googleのログインボタンを作成しているコード
// MARK: - Google Sign-In Button
struct GoogleSignInButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
HStack {
Image(systemName: "g.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.foregroundColor(.white)
Text("Sign in with Google")
.fontWeight(.semibold)
.font(.system(size: 18))
}
.frame(width: 250, height: 50)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(25)
}
.shadow(radius: 5)
}
}