纯SwiftUI架构iOS应用集成Plaid OAuth深度链接的教程求助及问题排查
Hey there, I see exactly where you're hitting a wall here. In a 100% SwiftUI app, your root view controller is a UIHostingController wrapping your SwiftUI views—not your BankAccountsView directly. That's why trying to cast it to LinkOAuthHandling fails at "FAIL 1" every time. Let's fix this with a cleaner, SwiftUI-native approach using an observable object to manage your Plaid Link state.
Step 1: Create a Shared Plaid Link Manager
First, make an ObservableObject that implements LinkOAuthHandling and holds your Link handler. This will let you share the handler across your app without relying on view controller casts:
import LinkKit import SwiftUI class PlaidLinkManager: ObservableObject, LinkOAuthHandling { @Published var linkHandler: Handler? let oauthRedirectUri: URL? = URL(string: "https://cruisedevelopment.page.link") func createLinkHandler(with configuration: LinkTokenConfiguration) { do { linkHandler = try Handler(configuration: configuration) { [weak self] result in // Handle Link result here (success/error/cancel) self?.linkHandler = nil } } catch { print("Failed to create Plaid Link handler: \(error)") } } }
Step 2: Inject the Manager into Your App's Environment
In your CruiseApp, add the manager to the environment so all views can access it:
@main struct CruiseApp: App { @StateObject private var plaidLinkManager = PlaidLinkManager() var body: some Scene { WindowGroup { ContentView() .environmentObject(plaidLinkManager) .onOpenURL { url in // Directly use the shared manager instead of casting view controllers guard let handler = plaidLinkManager.linkHandler else { print(">> FAIL: No active Link handler found") return } handler.continue(from: url) } } } }
Step 3: Update Your BankAccountsView to Use the Manager
Modify your BankAccountsView to use the environment object instead of holding its own handler:
struct BankAccountsView: View { @EnvironmentObject private var plaidLinkManager: PlaidLinkManager @State var configurationForCreate: LinkTokenConfiguration? @State var configurationForUpdate: LinkTokenConfiguration? @State var showPlaidModal = false var body: some View { // Your existing view content... Button("Connect Bank") { guard let config = configurationForCreate else { return } plaidLinkManager.createLinkHandler(with: config) showPlaidModal = true } .fullScreenCover(isPresented: $showPlaidModal) { if let handler = plaidLinkManager.linkHandler { LinkController(handler: handler) } } } }
Why This Works
- The
PlaidLinkManageris a single source of truth for your Link handler, shared across the app via SwiftUI's environment. - You no longer need to mess with
UIWindowor view controller casts—onOpenURLdirectly uses the shared handler. - The
LinkControlleris still used to present the Plaid modal, but it now gets the handler from the shared manager instead of the view itself.
Quick Notes
- Make sure you're still setting up your Link token correctly (either via your backend or Plaid's sandbox).
- When the Link flow completes (success/error/cancel), the manager resets the
linkHandlerto nil to avoid stale references.
内容的提问来源于stack exchange,提问作者blrsk

