You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置webAuthSession.presentationContextProvider = self时提示“找不到self”的问题求助

解决Web认证中"Cannot find 'self' in scope"错误

问题根源

你遇到的错误核心原因是:

  • webAuthSession实例和TeslaSignIn函数都定义在全局作用域,而非实现了ASWebAuthenticationPresentationContextProviding协议的SignInViewModel类内部,此时self没有对应的类实例上下文
  • 协议实现与认证会话逻辑完全分离,导致无法关联上下文提供者

修正后的完整代码

import Foundation
import AuthenticationServices
import CryptoKit
import UIKit

typealias ASPresentationAnchor = UIWindow

class SignInViewModel: NSObject, ObservableObject, ASWebAuthenticationPresentationContextProviding {
    // 将认证会话作为类属性,延迟初始化
    private var webAuthSession: ASWebAuthenticationSession?
    
    // 实现协议方法,返回当前应用的主窗口(修正原代码直接创建空窗口的问题)
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return UIApplication.shared.windows.first ?? ASPresentationAnchor()
    }
    
    // 生成认证URL的方法移到类内部,改为静态方法
    private static func generateAuthURL() -> URL {
        func randomString(length: Int) -> String {
            let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
            return String((0..<length).map{ _ in letters.randomElement()! })
        }
        
        let codeVerifier = randomString(length: 86)
        let hashData = Data(codeVerifier.utf8)
        let codeChallengeData = SHA256.hash(data: hashData)
        let codeChallenge = codeChallengeData.compactMap { String(format: "%02x", $0) }.joined()
        
        let baseURL = "https://auth.tesla.com/oauth2/v3/authorize"
        let parameters = [
            "client_id": "ownerapi",
            "code_challenge": codeChallenge,
            "code_challenge_method": "S256",
            "redirect_uri": "https://auth.tesla.com/void/callback",
            "response_type": "code",
            "scope": "openid+email+offline_access",
            "state": codeVerifier
        ]
        
        // 用URLComponents构建URL,避免字符串拼接的编码问题
        var components = URLComponents(string: baseURL)!
        components.queryItems = parameters.map { URLQueryItem(name: $0.key, value: $0.value) }
        return components.url!
    }
    
    // 登录方法改为类实例方法
    func teslaSignIn() {
        guard webAuthSession == nil else { return }
        
        webAuthSession = ASWebAuthenticationSession(
            url: Self.generateAuthURL(),
            callbackURLScheme: "TESRIUM",
            completionHandler: { [weak self] callbackURL, error in
                // 处理认证回调逻辑
                if let error = error {
                    print("认证错误:\(error.localizedDescription)")
                } else if let callbackURL = callbackURL {
                    print("回调URL:\(callbackURL)")
                    // 解析code等参数
                }
                // 重置会话
                self?.webAuthSession = nil
            }
        )
        
        webAuthSession?.presentationContextProvider = self
        webAuthSession?.prefersEphemeralWebBrowserSession = false
        webAuthSession?.start()
    }
}

关键修改说明

  1. 作用域调整:将所有认证相关逻辑移到SignInViewModel类内部,确保self指向实现了协议的类实例
  2. 会话管理:用private var webAuthSession: ASWebAuthenticationSession?存储会话实例,避免全局变量导致的生命周期问题
  3. URL构建优化:改用URLComponents生成认证URL,解决字符串拼接可能带来的编码错误
  4. 窗口获取修正:presentationAnchor返回当前应用的主窗口,而非创建新窗口,符合ASWebAuthenticationSession的要求
  5. 内存安全:在completionHandler中使用[weak self]避免循环引用

内容的提问来源于stack exchange,提问作者BlazeProg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:05:32