如何使用变量初始化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
相关产品推荐
相关产品推荐

