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

IOS Firestore离线访问异常:onSnapshot离线返回空白及报错求助

问题背景

我使用Capacitor开发App,AppDelegate配置代码如下:

import UIKit
import Capacitor
import Firebase
import FirebaseCore
import FirebaseDatabase
import FacebookCore

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        Database.database().isPersistenceEnabled = true
        ApplicationDelegate.shared.application(
         application,
         didFinishLaunchingWithOptions: launchOptions
        )
        return true
    }
}

查询逻辑代码:

const useItemsUser = () => {
  const user = firebase.auth().currentUser;
  const user1 = user.uid;
  const [items, setItems] = useState([]);
  useEffect(() => {
    const unsubscribe = firebase
      .firestore()
      .collection("user")
      .where("id", "==", `${user1}`)
      .onSnapshot(snapshot => {
        const listItemsUsers = snapshot.docs.map(doc => ({
          id: doc.id,
          ...doc.data()
        }));
        setItems(listItemsUsers);
      });
    return () => unsubscribe();
  }, []);
  return items;
};

离线状态下,查询返回空白结果,同时报错:

@firebase/firestore: Firestore (8.10.1): Connection WebChannel transport errored

我认为AppDelegate配置无误,问题可能出在onSnapshot上,求解决方法。


问题原因与解决方法

1. 核心问题:未开启Firestore离线持久化

你当前仅开启了Realtime Database的持久化(Database.database().isPersistenceEnabled = true),但没有配置Firestore的离线缓存功能。离线时Firestore没有本地数据可读取,自然返回空白结果。

在FirebaseApp.configure()之后添加Firestore持久化配置:

// 启用Firestore离线持久化
do {
    try Firestore.firestore().enablePersistence()
} catch {
    print("Firestore持久化启用失败: \(error)")
}

2. 优化onSnapshot的离线处理逻辑

onSnapshot默认会优先返回本地缓存数据,但需要显式监听元数据变化来确认数据来源,同时确保查询条件对应的文档已被缓存。修改查询代码:

.onSnapshot({ includeMetadataChanges: true }, snapshot => {
  // 区分数据来自缓存还是服务器
  if (snapshot.metadata.fromCache) {
    console.log("当前数据来自本地缓存");
  } else {
    console.log("当前数据来自服务器");
  }
  const listItemsUsers = snapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data()
  }));
  setItems(listItemsUsers);
});

添加includeMetadataChanges: true可以监听缓存与服务器数据的切换状态,方便排查问题。

3. 修复依赖数组的遗漏问题

你的useEffect依赖数组为空,但查询依赖user1(用户UID)。如果组件挂载时用户登录状态还未初始化,会导致查询使用无效UID,进而无法缓存到对应数据。将user1加入依赖数组:

useEffect(() => {
  if (!user1) return; // 避免UID为空时执行无效查询
  
  const unsubscribe = firebase
    .firestore()
    .collection("user")
    .where("id", "==", user1)
    .onSnapshot({ includeMetadataChanges: true }, snapshot => {
      const listItemsUsers = snapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
      }));
      setItems(listItemsUsers);
    });
  return () => unsubscribe();
}, [user1]); // 添加user1到依赖数组,确保UID变化时重新执行查询

4. 检查Firestore安全规则

如果自定义了Firestore安全规则,需确保离线时缓存的文档符合权限要求。默认规则下离线缓存可正常使用,若有特殊权限限制,需调整规则允许缓存数据的读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:08:31