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

Firestore数据已获取但返回数组为空的原因及解决方法

问题:Firestore数据获取函数返回空数组

我正在学习Swift,已经实现了从Firestore数据库获取数据的功能,通过Data Controller处理数据获取逻辑。调用接口能成功拿到数据(打印语句能看到),但自定义的fetchUnidades函数返回的[MyClassType]数组是空的。

函数代码如下:

func fetchUnidades(for foo: MyFirstEnum, and bar: MySecondEnum ) -> [MyClassType]{
    
    let db = Firestore.firestore()
    let colPath = "my/firebase/path"
    let results = [MyClassType]()
    let collection = db.collection(colPath)
    
    collection.whereField("myField", isEqualTo: foo.rawValue).getDocuments() { querySnapshot, err in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                do {
                    print("\(document.documentID) => \(document.data())") // 1st print
                    let newMyClass = try document.data(as: MyClassType.self)
                    results.append(newMyClass)
                    print("here") // 2nd print - debug breakpoint
                }catch (let error) {
                    print("\(error)")
                }
            }
        }
    }
    print("DC - Recovered \(results.count) results")
    return results
}

已知MyFirstEnum、MySecondEnum和MyClassType定义均正确,闭包内断点处打印results能看到已获取到数据,但函数执行到return语句时results为空,打印结果显示"DC - Recovered 0 results",返回的数组也为空。


问题原因

Firestore的getDocuments()是异步操作:它会在后台线程发起网络请求,不会阻塞当前主线程的执行流程。你的函数在调用getDocuments()后,立刻就执行了打印语句和return,这时候闭包还没开始执行(网络请求还没完成),所以results还是初始化时的空数组。等网络请求完成、闭包开始往results里添加数据时,函数早就已经返回空数组了。


解决方法

方法1:使用Completion Handler(兼容所有Swift版本)

修改函数,通过回调闭包返回结果,而不是直接返回数组:

func fetchUnidades(for foo: MyFirstEnum, and bar: MySecondEnum, completion: @escaping ([MyClassType]?, Error?) -> Void) {
    let db = Firestore.firestore()
    let colPath = "my/firebase/path"
    let collection = db.collection(colPath)
    
    collection.whereField("myField", isEqualTo: foo.rawValue).getDocuments() { querySnapshot, err in
        if let err = err {
            print("Error getting documents: \(err)")
            completion(nil, err)
            return
        }
        
        var results = [MyClassType]()
        for document in querySnapshot!.documents {
            do {
                print("\(document.documentID) => \(document.data())")
                let newMyClass = try document.data(as: MyClassType.self)
                results.append(newMyClass)
                print("here")
            } catch let error {
                print("\(error)")
            }
        }
        print("DC - Recovered \(results.count) results")
        completion(results, nil)
    }
}

调用示例:

fetchUnidades(for: .yourEnumCase, and: .anotherEnumCase) { unidades, error in
    if let error = error {
        // 处理错误逻辑
        return
    }
    // 在这里使用获取到的数据
    if let unidades = unidades {
        print("成功获取\(unidades.count)条数据")
    }
}

方法2:使用Async/Await(Swift 5.5+推荐)

如果你的项目使用Swift 5.5及以上版本,用异步等待语法可以让代码更简洁,逻辑更清晰:

func fetchUnidades(for foo: MyFirstEnum, and bar: MySecondEnum) async throws -> [MyClassType] {
    let db = Firestore.firestore()
    let colPath = "my/firebase/path"
    let collection = db.collection(colPath)
    
    // 异步等待请求完成
    let querySnapshot = try await collection.whereField("myField", isEqualTo: foo.rawValue).getDocuments()
    
    var results = [MyClassType]()
    for document in querySnapshot.documents {
        let newMyClass = try document.data(as: MyClassType.self)
        results.append(newMyClass)
        print("\(document.documentID) => \(document.data())")
    }
    print("DC - Recovered \(results.count) results")
    return results
}

调用示例(需要在异步上下文执行,比如Task中):

Task {
    do {
        let unidades = try await fetchUnidades(for: .yourEnumCase, and: .anotherEnumCase)
        // 使用获取到的数据
        print("成功获取\(unidades.count)条数据")
    } catch {
        // 处理错误
        print("获取数据失败:\(error)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:33:28