Flutter iOS端Firebase Apple登录无响应报NoSuchMethodError如何解决
问题修复方案
根因定位
- 你当前的权限配置完全正确,Apple授权、Firebase同步用户的链路已经跑通,报错和权限配置无关
NoSuchMethodError: The method '[]' was called on null. Tried calling: []("User")错误是上层代码拿到返回的null用户对象后,直接对空对象执行了["User"]取值操作导致的
具体修复步骤
步骤1:修复上层调用逻辑的空判断
你当前的signInWithApple方法在登录失败时会返回null的User对象,上层调用不能默认返回值非空,要先做空校验,示例:
// 错误写法 User user = await AuthenticationApple.signInWithApple(context: context); Map userInfo = user["User"]; // 登录失败时user为null,直接触发报错 // 正确写法 User? user = await AuthenticationApple.signInWithApple(context: context); if (user != null) { // 只有user非空时才执行后续操作 Map userInfo = user["User"]; // 其他登录成功后的逻辑 }
步骤2:补全signInWithApple方法的异常捕获
你当前的try-catch只覆盖了Firebase认证部分,Apple授权请求的部分没有做异常捕获,用户取消授权、网络异常都会导致方法中断返回null,修改后完整方法如下:
import 'dart:convert'; import 'dart:math'; import 'package:crypto/crypto.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:sign_in_with_apple/sign_in_with_apple.dart'; mixin AuthenticationApple { static String generateNonce([int length = 32]) { const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'; final random = Random.secure(); return List.generate(length, (_) => charset[random.nextInt(charset.length)]) .join(); } static String sha256ofString(String input) { final bytes = utf8.encode(input); final digest = sha256.convert(bytes); return digest.toString(); } static Future<User?> signInWithApple({BuildContext? context}) async { User? user; final rawNonce = generateNonce(); final nonce = sha256ofString(rawNonce); try { // 把Apple授权请求也放进try块捕获异常 final appleCredential = await SignInWithApple.getAppleIDCredential( scopes: [ AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName, ], nonce: nonce, ); // 新增身份令牌空校验,避免空值传入Firebase导致认证失败 if (appleCredential.identityToken == null) { if (context != null) { ScaffoldMessenger.of(context).showSnackBar( AppWidget.customSnackBar( content: '获取身份凭证失败,请重试', ), ); } return null; } final oauthCredential = OAuthProvider('apple.com').credential( idToken: appleCredential.identityToken!, rawNonce: rawNonce, ); final UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential); user = userCredential.user; } on SignInWithAppleAuthorizationException catch (e) { // 处理苹果授权异常,用户主动取消登录的情况不弹窗提示 if (e.code != AuthorizationErrorCode.canceled && context != null) { ScaffoldMessenger.of(context).showSnackBar( AppWidget.customSnackBar( content: '苹果授权失败,请重试', ), ); } } on FirebaseAuthException catch (e) { if (context != null) { String msg = ''; if (e.code == 'account-exists-with-different-credential') { msg = '该账号已通过其他方式注册,请使用其他登录方式'; } else if (e.code == 'invalid-credential') { msg = '凭证无效,请重试'; } else { msg = '登录失败,请重试'; } ScaffoldMessenger.of(context).showSnackBar( AppWidget.customSnackBar(content: msg), ); } } catch (e) { if (context != null) { ScaffoldMessenger.of(context).showSnackBar( AppWidget.customSnackBar( content: '登录异常,请重试', ), ); } } return user; } }
步骤3:确认User对象的取值方式
如果你的User对象是自定义类,要确认你是否正确实现了[]运算符,或者你是不是应该用.user之类的属性取值,而不是用["User"]的下标方式取值。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

