# How to Fix the Google Sign-In Popup Freeze on iOS

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-27. 7 min read.
> Source: https://vp0.com/blogs/google-sign-in-popup-freeze-ios-fix

A frozen Google Sign-In sheet on iOS almost always means a deallocated auth session or a bad presenting controller. Here is how to fix it for good.

**TL;DR.** The Google Sign-In popup freezes on iOS when the underlying web auth session is released before it finishes, or when it is presented from the wrong view controller, so the sheet appears but never responds. The fix is to hold a strong reference to the sign-in flow, present it from the top-most visible controller on the main thread, and set the presentation anchor correctly. Google's iOS SDK uses ASWebAuthenticationSession under the hood, so the same retain-and-present rules apply. Start the sign-in screen from a free VP0 design and wire the SDK in carefully.

A frozen Google Sign-In popup on iOS is almost never a network problem. The sheet opens and then stops responding because the web authentication session behind it was released before the user finished, or because it was presented from a view controller that is no longer on screen. The reliable fix is to hold a strong reference to the sign-in flow for its whole lifetime, present it from the top-most visible controller on the main thread, and set the presentation anchor correctly. The sign-in screen itself is fastest to start from a free [VP0](/explore) design, the same way you would build a [Firebase iOS auth login screen](/blogs/firebase-ios-auth-login-dark-mode/).

## What the freeze actually is

The symptom is specific: tapping the Google button opens the system web sheet, the page may even load, but nothing you do dismisses it or returns to the app. That is the signature of a callback that never fires, not a request that never sends. iOS presents the sign-in as a web session it expects you to keep alive until it completes; if the object that owns that session is deallocated mid-flow, the completion handler is orphaned and the sheet is stranded on screen.

So the diagnosis order matters. Treat a freeze as a lifecycle or presentation bug first, and only look at OAuth configuration if sign-in still fails after the sheet behaves.

## Why it happens: the retained session

Google's iOS SDK drives the sheet with [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession), Apple's system component for web-based auth. Apple's documentation is explicit that you must keep a strong reference to the session until it completes, because once it is deallocated the flow is cancelled. The same rule applies to the Google sign-in object that wraps it: if you kick off sign-in from a local variable that goes out of scope, or from a SwiftUI view that is recreated, the owning object dies and the sheet freezes.

The fix is to store the sign-in flow somewhere stable, a view model or a coordinator that outlives the view, so the session survives until the user finishes or cancels. The [Google Sign-In for iOS integration guide](https://developers.google.com/identity/sign-in/ios/start-integrating) shows the expected call shape; the missing piece in frozen apps is almost always ownership.

## Why it happens: the wrong presenting controller

The second cause is presenting from a controller that is not actually on screen. The sign-in needs a live presenting view controller, and in a SwiftUI app it is easy to hand it a stale one, a root captured at launch, or a controller inside a sheet that has since been dismissed. iOS then has no valid place to anchor the web session, and the result looks like a freeze.

Resolve the presenting controller at the moment of sign-in: find the active window scene, take its root, and walk to the top-most presented controller, then present from that. Doing this on the main thread matters too, since UI presentation off the main thread misbehaves in exactly this stuck-sheet way.

## A correct sign-in flow

Put the three fixes together and the flow is stable: own the sign-in object in a coordinator, resolve the live top-most controller, and present on the main thread.

```swift
@MainActor
final class AuthCoordinator: ObservableObject {
    func signIn() {
        guard let presenter = UIApplication.topMostViewController() else { return }
        GIDSignIn.sharedInstance.signIn(withPresenting: presenter) { [self] result, error in
            // self is retained for the whole flow; handle result or error here
        }
    }
}
```

Holding the coordinator as a `@StateObject`, resolving `topMostViewController` live, and keeping the call on `@MainActor` removes both freeze causes at once. The [Google Sign-In button in SwiftUI](/blogs/google-sign-in-button-swiftui-code/) is the surface; this coordinator is the plumbing behind it.

## Plan for two providers

While you are in the sign-in screen, plan for Apple's rule. The [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) require apps that offer a third-party or social login like Google to also offer Sign in with Apple as an equivalent option, with limited exceptions. Designing the screen to hold both buttons cleanly now avoids a forced redesign at review, and it pairs naturally with an [Apple sign-in template](/blogs/apple-sign-in-template-react-native/).

## What to choose

When the Google Sign-In popup freezes on iOS, fix it as a lifecycle bug, not a config one. Hold a strong reference to the sign-in flow in a coordinator or view model that outlives the view, resolve the top-most visible view controller at the moment of sign-in rather than reusing a stale one, and present on the main thread. That removes the orphaned-callback and stale-anchor causes that produce the stuck sheet. Only after the sheet behaves should you check the client ID and URL scheme. Plan for Sign in with Apple alongside Google to satisfy review, and start the screen from a free, $0 VP0 design so your effort goes into the auth wiring, not the layout.

## Frequently asked questions

### Why does the Google Sign-In popup freeze on iOS?

Almost always because the web authentication session backing the sign-in was released before the user finished, or it was presented from a controller that is no longer on screen. The sheet appears but its callbacks never fire, so it looks frozen. Hold a strong reference to the sign-in object for the whole flow, present it from the top-most visible view controller on the main thread, and the freeze stops. It is a lifecycle and presentation bug, not a network one.

### How do I present Google Sign-In from the right view controller?

Use the currently visible, top-most view controller as the presenting controller, not a cached reference from app launch or a controller inside a dismissed modal. In SwiftUI, resolve the active window scene's root and walk to its top-most presented controller at the moment of sign-in. Presenting from a stale or detached controller is a common cause of the frozen sheet, because iOS has nowhere valid to attach the web session.

### Does the freeze mean my Google OAuth config is wrong?

Usually not. A misconfigured client ID or URL scheme tends to fail with an error or never open the sheet at all, whereas a freeze is the sheet opening and then not responding, which points at lifecycle and presentation. Fix the retain and presenting-controller issues first. If sign-in still errors out after that, then check the client ID, the reversed-client-ID URL scheme, and your redirect handling.

### Do I still need Sign in with Apple if I offer Google Sign-In?

On iOS, if your app uses a third-party or social login such as Google, Apple's review guidelines require you to also offer Sign in with Apple as an equivalent option, with narrow exceptions. So plan for both buttons on the sign-in screen from the start. Building the screen to hold two providers cleanly avoids a redesign later and keeps the app on the right side of review.

### Can VP0 give me a free sign-in screen to build from?

Yes. VP0 is a free iOS design library where each screen has an AI-readable source page, so you copy a link and Claude Code or Cursor builds the sign-in screen in SwiftUI. You own the code and wire in the Google SDK yourself, applying the retain-and-present fixes. The design gives you a clean, two-provider layout to start from at no cost.

## Frequently asked questions

### Why does the Google Sign-In popup freeze on iOS?

Almost always because the web authentication session backing the sign-in was released before the user finished, or it was presented from a controller that is no longer on screen. The sheet appears but its callbacks never fire, so it looks frozen. Hold a strong reference to the sign-in object for the whole flow, present it from the top-most visible view controller on the main thread, and the freeze stops. It is a lifecycle and presentation bug, not a network one.

### How do I present Google Sign-In from the right view controller?

Use the currently visible, top-most view controller as the presenting controller, not a cached reference from app launch or a controller inside a dismissed modal. In SwiftUI, resolve the active window scene's root and walk to its top-most presented controller at the moment of sign-in. Presenting from a stale or detached controller is a common cause of the frozen sheet, because iOS has nowhere valid to attach the web session.

### Does the freeze mean my Google OAuth config is wrong?

Usually not. A misconfigured client ID or URL scheme tends to fail with an error or never open the sheet at all, whereas a freeze is the sheet opening and then not responding, which points at lifecycle and presentation. Fix the retain and presenting-controller issues first. If sign-in still errors out after that, then check the client ID, the reversed-client-ID URL scheme, and your redirect handling.

### Do I still need Sign in with Apple if I offer Google Sign-In?

On iOS, if your app uses a third-party or social login such as Google, Apple's review guidelines require you to also offer Sign in with Apple as an equivalent option, with narrow exceptions. So plan for both buttons on the sign-in screen from the start. Building the screen to hold two providers cleanly avoids a redesign later and keeps the app on the right side of review.

### Can VP0 give me a free sign-in screen to build from?

Yes. VP0 is a free iOS design library where each screen has an AI-readable source page, so you copy a link and Claude Code or Cursor builds the sign-in screen in SwiftUI. You own the code and wire in the Google SDK yourself, applying the retain-and-present fixes. The design gives you a clean, two-provider layout to start from at no cost.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
