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

如何使用变量初始化Firebase的@FirestoreQuery属性包装器

报错原因

该报错是Swift初始化规则的正常限制:结构体实例属性的初始化阶段,self尚未完成构造,无法引用同结构体下的其他实例成员作为初始化参数。

解决方案

方案1:自定义构造器手动初始化属性包装器

属性包装器的实际实例对应带下划线前缀的成员变量,你可以在自定义构造器中完成@FirestoreQuery的初始化,规避实例成员引用限制:

import SwiftUI
import FirebaseFirestoreSwift

struct TestFirestoreQuery: View {
    @State var itemLimit: Int
    let increment: Int = 5
    let path: String
    
    @FirestoreQuery fileprivate var MessageResults: Result<[Message_M], Error>
    
    // 自定义构造器
    init(initialLimit: Int = 5, path: String = "/discussions/blablabal/messages") {
        // 先初始化普通属性
        self._itemLimit = State(initialValue: initialLimit)
        self.path = path
        // 手动初始化FirestoreQuery属性包装器
        self._MessageResults = FirestoreQuery(
            collectionPath: path,
            predicates: [
                .order(by: "dateCreated", descending: true),
                .limit(to: initialLimit)
            ]
        )
    }
    
    // 原有body逻辑无需修改
    var body: some View {
        VStack {
            if case let .success(Messages) = MessageResults {
                List(Messages.reversed()) { message in
                    Text("\(message.msg)")
                }
                .refreshable{
                    itemLimit += increment
                    $MessageResults.predicates = [
                        .order(by: "dateCreated", descending: true),
                        .limit(to: itemLimit)
                    ]
                }
            }
            else if case let .failure(error) = MessageResults {
                Text("Couldn't map data: \(error.localizedDescription)")
            }
            Button {
                itemLimit += increment
                $MessageResults.predicates = [
                    .order(by: "dateCreated", descending: true),
                    .limit(to: itemLimit)
                ]
            } label: {
                Text("Tap me!")
                    .padding()
                    .foregroundColor(.white)
                    .background(.red)
            }
        }
    }
}

方案2:占位初始化+动态修改参数

如果参数是View内部的动态变量,你可以先给@FirestoreQuery设置临时占位参数,在页面加载完成后更新为真实的查询配置:

struct TestFirestoreQuery: View {
    @State var itemLimit: Int = 5
    let increment: Int = 5
    let path: String = "/discussions/blablabal/messages"
    
    // 临时占位初始化
    @FirestoreQuery(collectionPath: "/placeholder", predicates: []) fileprivate var MessageResults: Result<[Message_M], Error>
    
    var body: some View {
        VStack {
            // 原有视图逻辑不变
        }
        .onAppear {
            // 替换为真实查询参数
            $MessageResults.collectionPath = path
            $MessageResults.predicates = [
                .order(by: "dateCreated", descending: true),
                .limit(to: itemLimit)
            ]
        }
    }
}

补充:固定参数场景简化方案

如果你的查询路径、默认限制是固定不变的常量,可以直接声明为静态属性,即可直接在属性包装器初始化参数中引用:

struct TestFirestoreQuery: View {
    @State var itemLimit: Int = 5
    let increment: Int = 5
    // 声明为静态属性,属于类型而非实例,初始化阶段可访问
    static let path: String = "/discussions/blablabal/messages"
    static let defaultLimit: Int = 5
    
    @FirestoreQuery(collectionPath: Self.path,
                    predicates: [
                        .order(by: "dateCreated", descending: true),
                        .limit(to: Self.defaultLimit)
                    ]
    ) fileprivate var MessageResults: Result<[Message_M], Error>
    
    // 原有body逻辑不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:45:08