瀏覽代碼

Support Swift6 version to Birthday sample app. (#544)

subkumar 7 月之前
父節點
當前提交
0bd758739a

+ 2 - 2
Samples/Swift/DaysUntilBirthday/Shared/Services/GoogleSignInAuthenticator.swift

@@ -29,7 +29,7 @@ final class GoogleSignInAuthenticator: ObservableObject {
 
   /// Signs in the user based upon the selected account.'
   /// - note: Successful calls to this will set the `authViewModel`'s `state` property.
-  func signIn() {
+  @MainActor func signIn() {
 #if os(iOS)
     guard let rootViewController = UIApplication.shared.windows.first?.rootViewController else {
       print("There is no root view controller!")
@@ -98,7 +98,7 @@ final class GoogleSignInAuthenticator: ObservableObject {
   /// `addScopes(_:presenting:)` request.
   /// - note: Successful requests will update the `authViewModel.state` with a new current user that
   /// has the granted scope.
-  func addBirthdayReadScope(completion: @escaping () -> Void) {
+  @MainActor func addBirthdayReadScope(completion: @escaping () -> Void) {
     guard let currentUser = GIDSignIn.sharedInstance.currentUser else {
       fatalError("No user signed in!")
     }

+ 34 - 22
Samples/Swift/DaysUntilBirthday/Shared/Services/UserProfileImageLoader.swift

@@ -22,38 +22,50 @@ typealias GIDImage = NSImage
 
 import Combine
 import SwiftUI
-import GoogleSignIn
+@preconcurrency import GoogleSignIn
 
 /// An observable class for loading the current user's profile image.
-final class UserProfileImageLoader: ObservableObject {
+@MainActor final class UserProfileImageLoader: ObservableObject {
   private let userProfile: GIDProfileData
-  private let imageLoaderQueue = DispatchQueue(label: "com.google.days-until-birthday")
+  private var imageLoadingTask: Task<Void, Never>?
   /// A `UIImage` property containing the current user's profile image.
   /// - note: This will default to a placeholder, and updates will be published to subscribers.
   @Published var image = GIDImage(named: "PlaceholderAvatar")!
 
   /// Creates an instance of this loader with provided user profile.
   /// - note: The instance will asynchronously fetch the image data upon creation.
-  init(userProfile: GIDProfileData) {
-    self.userProfile = userProfile
-    guard userProfile.hasImage else {
-      return
+    init(userProfile: GIDProfileData) {
+        self.userProfile = userProfile
+        guard userProfile.hasImage else {
+            return
+        }
+        imageLoadingTask = Task {
+            await loadProfileImage()
+        }
     }
 
-    imageLoaderQueue.async {
-      #if os(iOS)
-      let dimension = 45 * UIScreen.main.scale
-      #elseif os(macOS)
-      let dimension = 120
-      #endif
-      guard let url = userProfile.imageURL(withDimension: UInt(dimension)),
-            let data = try? Data(contentsOf: url),
-            let image = GIDImage(data: data) else {
-        return
-      }
-      DispatchQueue.main.async {
-        self.image = image
-      }
+    private func loadProfileImage() async {
+    #if os(iOS)
+        let dimension = 45 * UIScreen.main.scale
+    #elseif os(macOS)
+        let dimension = 120
+    #endif
+
+        guard let url = userProfile.imageURL(withDimension: UInt(dimension)) else {
+            return
+        }
+
+        do {
+            let (imageData, _) = try await URLSession.shared.data(from: url)
+            if let image = GIDImage(data: imageData) {
+                self.image = image
+            }
+        } catch {
+            print("Image download failed:", error)
+        }
+    }
+
+    deinit {
+        imageLoadingTask?.cancel()
     }
-  }
 }

+ 3 - 3
Samples/Swift/DaysUntilBirthday/Shared/ViewModels/AuthenticationViewModel.swift

@@ -46,7 +46,7 @@ final class AuthenticationViewModel: ObservableObject {
   }
 
   /// Signs the user in.
-  func signIn() {
+  @MainActor func signIn() {
     authenticator.signIn()
   }
 
@@ -66,8 +66,8 @@ final class AuthenticationViewModel: ObservableObject {
 
   /// Adds the requested birthday read scope.
   /// - parameter completion: An escaping closure that is called upon successful completion.
-  func addBirthdayReadScope(completion: @escaping () -> Void) {
-    authenticator.addBirthdayReadScope(completion: completion)
+  @MainActor func addBirthdayReadScope(completion: @escaping () -> Void) {
+      authenticator.addBirthdayReadScope(completion: completion)
   }
 
 }