Swiftui @状态初始值未在init()上重置变量
我有一个分段控件,我正在使用它作为我的应用程序工具栏中链接到selectedTab变量的选项卡。切换选项卡时,帐户列表会更改,但不会重置行列表。我尝试在所选的上使用initialValue以确保它重置为0,但这没有影响它。我尝试在init中打印,以确保在init之后selected的值为0。每次都是这样,但仍然没有刷新每个列表的行 我错过了什么Swiftui @状态初始值未在init()上重置变量,swiftui,Swiftui,我有一个分段控件,我正在使用它作为我的应用程序工具栏中链接到selectedTab变量的选项卡。切换选项卡时,帐户列表会更改,但不会重置行列表。我尝试在所选的上使用initialValue以确保它重置为0,但这没有影响它。我尝试在init中打印,以确保在init之后selected的值为0。每次都是这样,但仍然没有刷新每个列表的行 我错过了什么 import SwiftUI import SQLite3 struct ContentView:View { @EnvironmentOb
import SwiftUI
import SQLite3
struct ContentView:View {
@EnvironmentObject var shared:SharedObject
var body: some View {
VStack {
if shared.selectedTab == 0 {
LedgerView(ledger: .Accounts)
} else if shared.selectedTab == 1 {
LedgerView(ledger: .Budgets)
} else if shared.selectedTab == 2 {
ReportsView()
}
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct LedgerView:View {
@EnvironmentObject var shared:SharedObject
let ledger:LedgerType
@State var selected:Int = 0
init(ledger:LedgerType) {
self.ledger = ledger
self._selected = State(initialValue: 0)
}
var body:some View {
HStack {
VStack(alignment: HorizontalAlignment.leading) {
ForEach(shared.accounts.filter({$0.ledger == ledger})) { account in
Text(account.name)
.background(account.id == self.selected ? Color.accentColor : Color.clear)
.onTapGesture {self.selected = account.id}
}
}
Divider()
VStack(alignment: HorizontalAlignment.leading) {
ForEach(shared.journalLines.filter({$0.accountID == selected})) { line in
Text("Line#\(line.id)")
}
}
}
}
}
struct ReportsView:View {
var body:some View {
Text("Under Construction ...")
}
}
class SharedObject:ObservableObject {
@Published var accounts:[Account] = []
@Published var journalLines:[JournalLine] = []
@Published var selectedTab:Int = 0
init() {
loadData()
}
}
enum LedgerType:Int {
case Accounts=0,Budgets=1
var name:String {
switch(self) {
case .Accounts: return "Accounts"
case .Budgets: return "Budgets"
}
}
}
struct Account:Identifiable {
var id:Int
var name:String
var ledger:LedgerType
}
struct Payee:Identifiable {
var id:Int
var name:String
}
struct Journal:Identifiable {
var id:Int
var date:Date
var payeeID:Int
var memo:String?
}
struct JournalLine:Identifiable {
var id:Int
var journalID:Int
var accountID:Int
var amount:Double
}
编辑节略的演示代码,尝试隔离问题
import SwiftUI
struct ContentView: View {
@EnvironmentObject var shared:SharedObject
var body: some View {
VStack {
Picker(selection: $shared.selectedTab, label: Text("")) {
Text("Accounts").tag(0)
Text("Budgets").tag(1)
}.pickerStyle(SegmentedPickerStyle())
Divider()
if shared.selectedTab == 0 || shared.selectedTab == 1 {
LedgerView()
}
Spacer()
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct LedgerView:View {
@State var selected:Int = 0
init() {
self._selected = State(initialValue: 0)
print("LedgerView.init()")
}
var body:some View {
VStack(alignment: HorizontalAlignment.leading) {
Text("Selected: \(selected)")
Picker(selection: $selected, label: Text("")) {
Text("Account#1").tag(1)
Text("Account#2").tag(2)
Text("Account#3").tag(3)
}
}
}
}
class SharedObject: ObservableObject {
@Published var selectedTab:Int = 0
}
根据你最近的评论,你需要的是@Binding而不是@State。解释:struct LedgerView只是一个单独视图中选择器的摘录。调用LedgerView()时,不会实例化新对象。它只是在该位置添加选择器视图。因此,当需要在切换选项卡上重置选择器时,需要使用绑定重置选择器。这是工作代码。希望能有帮助
struct ContentView: View {
@EnvironmentObject var shared:SharedObject
@State var selected: Int = 0
var body: some View {
VStack {
Picker(selection: $shared.selectedTab, label: Text("")) {
Text("Accounts").tag(0)
Text("Budgets").tag(1)
}.pickerStyle(SegmentedPickerStyle())
Divider()
if shared.selectedTab == 0 || shared.selectedTab == 1 {
LedgerView(selected: $selected)
}
Spacer()
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onReceive(shared.$selectedTab) { newValue in
self.selected = 0
}
}
}
struct LedgerView:View {
@Binding var selected: Int
var body:some View {
VStack(alignment: HorizontalAlignment.leading) {
Text("Selected: \(selected)")
Picker(selection: $selected, label: Text("")) {
Text("Account#1").tag(1)
Text("Account#2").tag(2)
Text("Account#3").tag(3)
}
}
}
}
[先前的答案包含替代解决方案] 我已经修改了你的代码使代码行正常工作。我添加了示例数据以使代码正常工作。我怀疑问题是否出在你的数据上。此外,我还修改了enum LedgerType,使其具有可移植性。这是工作代码 我在代码中修改了以下内容:
struct ContentView:View {
@EnvironmentObject var shared: SharedObject
var body: some View {
VStack {
Picker(selection: $shared.selectedTab, label: Text("")) {
ForEach(0 ..< LedgerType.allCases.count) { index in
Text(LedgerType.allCases[index].rawValue).tag(index)
}
}
.pickerStyle(SegmentedPickerStyle())
if shared.selectedTab == 0 || shared.selectedTab == 1 {
LedgerView()
} else if shared.selectedTab == 2 {
ReportsView()
}
Spacer()
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct LedgerView:View {
@EnvironmentObject var shared:SharedObject
@State var selected: Int = 0
var body:some View {
HStack {
VStack(alignment: HorizontalAlignment.leading) {
ForEach(shared.accounts.filter({ $0.ledger == LedgerType.allCases[shared.selectedTab] })) { account in
Text(account.name)
.background(account.id == self.selected ? Color.accentColor : Color.clear)
.onTapGesture {self.selected = account.id}
}
}
Divider()
VStack(alignment: HorizontalAlignment.leading) {
ForEach(shared.journalLines.filter({$0.accountID == selected})) { line in
Text("Line#\(line.id)")
}
}
}
.onReceive(shared.$selectedTab) { newValue in
if let id = self.shared.getInitialAccountId(tabIndex: newValue) {
self.selected = id
}
}
}
}
struct ReportsView:View {
var body:some View {
Text("Under Construction ...")
}
}
class SharedObject:ObservableObject {
@Published var accounts:[Account] = []
@Published var journalLines:[JournalLine] = []
@Published var selectedTab:Int = 0
func getInitialAccountId(tabIndex: Int) -> Int? {
if tabIndex == 0 {
return accounts.filter({
$0.ledger == LedgerType.Accounts
}).first?.id
}
else if tabIndex == 1 {
return accounts.filter({
$0.ledger == LedgerType.Budgets
}).first?.id
}
else {
return accounts.filter({
$0.ledger == LedgerType.Reports
}).first?.id
}
}
init() {
accounts = [
Account(id: 1, name: "Sales", ledger: .Accounts),
Account(id: 2, name: "Purchase", ledger: .Accounts),
Account(id: 3, name: "Forecast", ledger: .Budgets)
]
journalLines = [
// Line for sales
JournalLine(id: 1, journalID: 10, accountID: 1, amount: 200),
JournalLine(id: 2, journalID: 20, accountID: 1, amount: 400),
// Line for purchase
JournalLine(id: 3, journalID: 30, accountID: 2, amount: 600),
JournalLine(id: 4, journalID: 40, accountID: 2, amount: 800)
]
}
}
enum LedgerType: String, CaseIterable {
case Accounts = "Accounts"
case Budgets = "Budgets"
case Reports = "Reports"
}
struct Account:Identifiable {
var id:Int
var name:String
var ledger:LedgerType
}
struct Payee:Identifiable {
var id:Int
var name:String
}
struct Journal:Identifiable {
var id:Int
var date:Date
var payeeID:Int
var memo:String?
}
struct JournalLine:Identifiable {
var id:Int
var journalID:Int
var accountID:Int
var amount:Double
}
struct ContentView:View{
@环境对象变量共享:SharedObject
var body:一些观点{
VStack{
选择器(选择:$shared.selectedTab,标签:文本(“”)){
ForEach(0..Int{
如果tabIndex==0{
返回帐户.filter({
$0.ledger==LedgerType.Accounts
}).第一个?.身份证
}
如果tabIndex==1,则为else{
返回帐户.filter({
$0.ledger==LedgerType.Budgets
}).第一个?.身份证
}
否则{
返回帐户.filter({
$0.ledger==LedgerType.Reports
}).第一个?.身份证
}
}
init(){
账户=[
账户(id:1,名称:“销售”,分类账:。账户),
账户(id:2,名称:“采购”,分类账:。账户),
账户(id:3,名称:“预测”,分类账:。预算)
]
日记行=[
//销售线
日记行(id:1,日记id:10,帐户id:1,金额:200),
日记行(id:2,日记id:20,帐户id:1,金额:400),
//购买线
日记行(id:3,日记id:30,帐户id:2,金额:600),
日记行(id:4,日记id:40,accountID:2,金额:800)
]
}
}
枚举分类帐类型:字符串,可大小写{
case Accounts=“Accounts”
案例预算=“预算”
案例报告=“报告”
}
结构帐户:可识别{
变量id:Int
变量名称:String
var分类账:分类账类型
}
结构收款人:可识别{
变量id:Int
变量名称:String
}
结构日志:可识别{
变量id:Int
var日期:日期
变量payeid:Int
var备注:字符串?
}
结构日志行:可识别{
变量id:Int
var journalID:Int
var accountID:Int
风险价值金额:双倍
}
根据您最近的评论,您需要的是@Binding而不是@State。解释:struct LedgerView只是一个单独视图中选择器的摘录。调用LedgerView()时,不会实例化新对象。它只是在该位置添加选择器视图。因此,当需要在切换选项卡上重置选择器时,需要使用绑定重置选择器。这是工作代码。希望能有帮助
struct ContentView: View {
@EnvironmentObject var shared:SharedObject
@State var selected: Int = 0
var body: some View {
VStack {
Picker(selection: $shared.selectedTab, label: Text("")) {
Text("Accounts").tag(0)
Text("Budgets").tag(1)
}.pickerStyle(SegmentedPickerStyle())
Divider()
if shared.selectedTab == 0 || shared.selectedTab == 1 {
LedgerView(selected: $selected)
}
Spacer()
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onReceive(shared.$selectedTab) { newValue in
self.selected = 0
}
}
}
struct LedgerView:View {
@Binding var selected: Int
var body:some View {
VStack(alignment: HorizontalAlignment.leading) {
Text("Selected: \(selected)")
Picker(selection: $selected, label: Text("")) {
Text("Account#1").tag(1)
Text("Account#2").tag(2)
Text("Account#3").tag(3)
}
}
}
}
[先前的答案包含替代解决方案] 我已经修改了你的代码使代码行正常工作。我添加了示例数据以使代码正常工作。我怀疑问题是否出在你的数据上。我也