根据@State变量的值更改重新加载视图



我的视图顶部有一个选项卡。选项卡是动态的,选项卡下方显示的ListView((取决于选项卡索引。对于选项卡0索引,ListView((是固定的,但从索引1开始,ListView(。因此,我当前选择的选项卡如下所示:

@State private var selectedTabIndex = 0

我现在正在重新加载静态视图,如下所示:

if self.selectedTabIndex == 0 {
ListView(id: selectedTabIndex)
} else if self.selectedTabIndex == 1 {
ListView(id: selectedTabIndex)          
} else if self.selectedTabIndex == 2 {
ListView(id: selectedTabIndex)       
} else if self.selectedTabIndex == 3 {
ListView(id: selectedTabIndex)
} else if self.selectedTabIndex == 4 {
ListView(id: selectedTabIndex)
} else if self.selectedTabIndex == 5 {
ListView(id: selectedTabIndex)
}

这很好,也可以重新加载ListView((,但这不是正确的方法,因为选项卡索引或多或少都是动态的。所以我尝试了这样的方法,因为当我点击选项卡时,我的selectedTabIndex值发生了变化:

if self.selectedTabIndex == 0 {
ListView(id: selectedTabIndex)
} else {
ListView(id: selectedTabIndex)
}

但它只重新加载第一次单击的选项卡,而不加载其他选项卡。我该怎么修?由于我是SwiftUI的新手,有时我会觉得很难。请帮忙。

更多详细信息:

import SwiftUI
struct WorkView: View {
@EnvironmentObject var navBarPreference: NavBarPreferences
@State private var selectedTabIndex = 0
@State private var isEmpty: Bool = true //
@State private var showWorkDetailView:Bool = false
@State var isCategoryAvailable:Bool = false
@ObservedObject var WorkVM = WorkViewModel() //
@State var workCategoryName: [String] = [" "]
@State var workCategoryID: [Int] = [0]
@State var selectedID: Int = 0
@State var workContentModel = [WorkContentModel]() //
var body: some View {
VStack(spacing: 0) {
HeaderView(title: "ワーク")
VStack {

if self.workCategoryName.isEmpty == false {
SlidingTab(selection: $selectedTabIndex, tabs: self.workCategoryName).padding(.top, 10)
}

}

Spacer().frame(maxHeight: 24)

//(selectedTabIndex == 0 ? SelectedFirstTab() : Text("Second View")).padding()

if self.selectedTabIndex == 0 {
SelectedFirstTab(selectedTabIndex: self.selectedTabIndex, isCategoryAvailable: self.$isCategoryAvailable, workCategoryName: self.$workCategoryName, workCategoryID: self.$workCategoryID, selectedID: self.$selectedID)
} else if self.selectedTabIndex == 1 {
SelectedFirstTab(selectedTabIndex: self.selectedTabIndex, isCategoryAvailable: self.$isCategoryAvailable, workCategoryName: self.$workCategoryName, workCategoryID: self.$workCategoryID, selectedID: self.$workCategoryID[self.selectedTabIndex])
} else if self.selectedTabIndex == 2 {
SelectedFirstTab(selectedTabIndex: self.selectedTabIndex, isCategoryAvailable: self.$isCategoryAvailable, workCategoryName: self.$workCategoryName, workCategoryID: self.$workCategoryID, selectedID: self.$workCategoryID[self.selectedTabIndex])
} else if self.selectedTabIndex == 3 {
SelectedFirstTab(selectedTabIndex: self.selectedTabIndex, isCategoryAvailable: self.$isCategoryAvailable, workCategoryName: self.$workCategoryName, workCategoryID: self.$workCategoryID, selectedID: self.$workCategoryID[self.selectedTabIndex])
} else if self.selectedTabIndex == 4 {
SelectedFirstTab(selectedTabIndex: self.selectedTabIndex, isCategoryAvailable: self.$isCategoryAvailable, workCategoryName: self.$workCategoryName, workCategoryID: self.$workCategoryID, selectedID: self.$workCategoryID[self.selectedTabIndex])
} else if self.selectedTabIndex == 5 {
SelectedFirstTab(selectedTabIndex: self.selectedTabIndex, isCategoryAvailable: self.$isCategoryAvailable, workCategoryName: self.$workCategoryName, workCategoryID: self.$workCategoryID, selectedID: self.$workCategoryID[self.selectedTabIndex])
}

//Spacer()
}.frame(minWidth: SCREEN_WIDTH)

//.position(x: SCREEN_WIDTH/2, y: SCREEN_HEIGHT/2)
//            .background(
//                Image("PPImage")
//                    .resizable()
//                    .frame(minWidth: 375, minHeight: 945)
//                //.aspectRatio(contentMode: .fit)
//        )
.edgesIgnoringSafeArea(.top)
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(self.navBarPreference.navBarIsHidden)
.navigationBarBackButtonHidden(self.navBarPreference.navigationBarBackButtonHidden)
.onAppear{ self.navBarPreference.navBarIsHidden = true
self.navBarPreference.navigationBarBackButtonHidden = true }
}
}
struct SelectedFirstTab: View {
@State private var isEmpty: Bool = true
@ObservedObject var WorkVM = WorkViewModel()
@State var workContentModel = [WorkContentModel]()
var selectedTabIndex: Int = 0
@Binding var isCategoryAvailable:Bool
@Binding var workCategoryName: [String]
@Binding var workCategoryID: [Int]
@Binding var selectedID: Int

var body: some View {
VStack {
if self.workContentModel.isEmpty {
EmptyContent()
} else {
ScrollView(showsIndicators: false) {
ForEach(self.workContentModel) { content in
NavigationLink(destination: WorkDetailView(data: content)) {
WorkViewRow(data: content)
}.frame(minWidth: SCREEN_WIDTH, minHeight: 118)
.padding(.top, 5)
.padding(.bottom, 5)
}
}.frame(maxHeight: 600)
}
}
.onAppear {

if self.isCategoryAvailable == false {
self.WorkVM.getWorkList() { workCategory, content in
for i in 0..<workCategory.count {
self.workCategoryName.append(workCategory[i].name ?? " ")
self.workCategoryID.append(workCategory[i].id ?? 0)
}
self.workCategoryName.removeFirst()

self.workContentModel = content
self.isCategoryAvailable = true
self.isEmpty = false

// print("myContent:(content)")
// print("workCategoryID:(self.workCategoryID)")

self.selectedID = self.workCategoryID[self.selectedTabIndex]
print("selectedID:(self.selectedID)")

}

} else if self.isCategoryAvailable == true {
self.WorkVM.getCategory(id: self.selectedID) { content in
self.workContentModel = content
self.isEmpty = false
self.selectedID = self.workCategoryID[self.selectedTabIndex]
print("selectedID:(self.selectedID)")
}
}

}
}
}
struct EmptyContent: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(.clear)
.frame(maxHeight: 600)

VStack {
Image("EmptyBackgroundImage")
.resizable()
.frame(maxWidth: 150, maxHeight: 146)
CustomizedText(text: "表示されるワークは n ありません", tracking: 2.2, frameHeight: 72, fontFamily: "HiraginoSans-W6", fontFamilySize: 22, lineLimit: 2)
.frame(maxWidth: 218, maxHeight: 72)
CustomizedText(text: "ここではワーク情報をお届けします。n 最新のワークを探していますのでお待ちください。", tracking: 1.2, frameHeight: 42, fontFamily: "HiraginoSans-W3", fontFamilySize: 12, lineLimit: 2).frame(maxWidth: 333, maxHeight: 42)
Spacer().frame(maxHeight: 210)

}
}
}
}

滑块

import SwiftUI
struct SlidingTab: View {
// Internal state to keep track of the selection index
@State private var selectionState: Int = 0 {
didSet {
selection = selectionState
}
}
// Binding the selection index which will  re-render the consuming view
@Binding var selection: Int
// The title of the tabs
private var tabs: [String]
init(selection: Binding<Int>, tabs: [String]) {
self._selection = selection
self.tabs = tabs
}
var body: some View {
VStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 24.scale()) {
ForEach(self.tabs, id: .self) { tab in
VStack {
Text(tab)
.frame(maxHeight: 55)
.font(.custom("HiraginoSans-W6", size: 15))
.foregroundColor(self.selection == self.tabs.firstIndex(of: tab) ? APP_TEXT_COLOR : APP_TEXT_COLOR.opacity(0.5))

Rectangle()
.frame(maxHeight: 3)
.foregroundColor(self.selection == self.tabs.firstIndex(of: tab) ? APP_COLOR : Color.clear)
.animation(.linear(duration: 0.25))

}.fixedSize()
.onTapGesture {
withAnimation {
let selection = self.tabs.firstIndex(of: tab) ?? 0
self.selectionState = selection
}
}
}
}.padding(.horizontal, 20.scale())
}
}

}
}

我的ViewModel:

import Foundation
import Combine
import Alamofire
import SwiftyJSON
class WorkViewModel: ObservableObject {
var updateValue =  PassthroughSubject<WorkViewModel, Never>()
@Published var workCategory = [WorkCategoryModel]() {
willSet {
updateValue.send(self)
}
}
@Published var workContent = [WorkContentModel]() {
willSet {
updateValue.send(self)
}
}
func getWorkList(completionHandler: @escaping ([WorkCategoryModel], [WorkContentModel]) -> Void) {
AF.request(Router.get(endpoint: "/mobile/works/top"))
.responseDecodable(of: WorkTabModel.self) { response in

print("Original URL request WorkList Tab:(String(describing: response.request))")

switch response.result {
case let .success(value):
if let workCategory = value.data.workCategories {
self.workCategory.append(contentsOf: workCategory)
}
// print("workCategory**:(self.workCategory)")

if let workContent = value.data.work?.content {
self.workContent.append(contentsOf: workContent)
}
print("workContent**:(self.workContent)")
completionHandler(self.workCategory, self.workContent)
case let .failure(error):
print("WorkModel Error**:(error)")
}
}

}
func getCategory(id: Int, completionHandler: @escaping ([WorkContentModel]) -> Void) {
let urlString = "(baseUrl)/mobile/works/top?work_category_id=(id)"
let userToken = UserDefaults.standard.value(forKey: "access_token") ?? ""
let token = "Bearer (userToken)"
let headers: HTTPHeaders = [
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": token
]
AF.request(urlString, headers: headers)
.responseJSON { response in
print("Original URL request WorkList Category:(String(describing: response.request))")
print("Category JSON response:(response)")
}
.responseDecodable(of: WorkTabModel.self) { response in

print("Original URL request WorkList Tab:(String(describing: response.request))")

switch response.result {
case let .success(value):
if let workContent = value.data.work?.content {
self.workContent.append(contentsOf: workContent)
}
print("workContent**:(self.workContent)")
completionHandler(self.workContent)
case let .failure(error):
print("WorkModel Error**:(error)")
}
}

}
}

最后我得到了解决方案。我从.onAapper{}调用API,当我单击顶部滑块上的不同选项卡时,我得到了一个id,使用该id我想调用相同的API,但使用id。即使我为id使用了@State变量,视图也没有重新加载。因此,我从.onTapGesture{}调用了API。但我仍然遇到了一些困难,因为.OnTapGesteture{}@State值同时变化。因此,我使用了DispatchQueue.main.asyncAfter,并使用其中的@State值调用API。我正在分享下面的代码,如果这可能有助于某人:

struct WorkView: View {
@EnvironmentObject var navBarPreference: NavBarPreferences
@State private var selectedTabIndex = 0
@State private var showWorkDetailView:Bool = false
@State var isCategoryAvailable:Bool = false
@ObservedObject var WorkVM = WorkViewModel() //
@State var workCategoryName: [String] = [" "]
@State var workCategoryID: [Int] = [0]
@State var workContentModel = [WorkContentModel]()
@State var hasShown: Bool = false
var body: some View {
VStack(spacing: 0) {
HeaderView(title: "ワーク")
VStack {
if self.workCategoryName.isEmpty == false {
SlidingTab(selection: $selectedTabIndex, tabs: self.workCategoryName).padding(.top, 10)
.onTapGesture {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
if self.isCategoryAvailable == true {
self.hasShown = true
//self.workContentModel.removeAll()
print("myWorkCategoryIDs:(self.workCategoryID)")
print("mySelectedIndex:(self.selectedTabIndex)")
let mySelectedID = self.workCategoryID[self.selectedTabIndex]
self.WorkVM.workContent.removeAll()
self.workContentModel.removeAll()
self.getContent(id: mySelectedID)
}
}
}
}
}

Spacer().frame(maxHeight: 24)

//(selectedTabIndex == 0 ? SelectedFirstTab() : Text("Second View")).padding()
VStack {
if self.workContentModel.isEmpty {
EmptyContent()
} else {
ScrollView(showsIndicators: false) {
ForEach(self.workContentModel) { content in
//Text("hihihihihihihihihi").frame(minWidth: 100, minHeight: 118)
NavigationLink(destination: WorkDetailView(data: content)) {
WorkViewRow(data: content)
}.frame(minWidth: SCREEN_WIDTH, minHeight: 118)
.padding(.top, 5)
.padding(.bottom, 5)
}
}.frame(maxHeight: 600)
}
}

//Spacer()
}.frame(minWidth: SCREEN_WIDTH)
.edgesIgnoringSafeArea(.top)
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(self.navBarPreference.navBarIsHidden)
.navigationBarBackButtonHidden(self.navBarPreference.navigationBarBackButtonHidden)
.onAppear{ self.navBarPreference.navBarIsHidden = true
self.navBarPreference.navigationBarBackButtonHidden = true

if (self.hasShown == false && self.isCategoryAvailable == false) {
self.WorkVM.workContent.removeAll()
self.workContentModel.removeAll()
self.getCategoryWithContent()
}
}


}
func getCategoryWithContent() {
self.WorkVM.getWorkList() { workCategory, content in
for i in 0..<workCategory.count {
self.workCategoryName.append(workCategory[i].name ?? " ")
self.workCategoryID.append(workCategory[i].id ?? 0)
}
self.workCategoryName.removeFirst()

self.workContentModel = content
self.isCategoryAvailable = true

print("selectedTabIndex:(self.selectedTabIndex)")
print("getCategoryWithContent called")

}
}
func getContent(id: Int) {
self.WorkVM.getCategory(id: id) { content in
self.workContentModel = content
print("selectedTabIndex:(self.selectedTabIndex)")
print("getContent called")
}
}
}

struct EmptyContent: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(.clear)
.frame(maxHeight: 600)

VStack {
Image("EmptyBackgroundImage")
.resizable()
.frame(maxWidth: 150, maxHeight: 146)
CustomizedText(text: "表示されるワークは n ありません", tracking: 2.2, frameHeight: 72, fontFamily: "HiraginoSans-W6", fontFamilySize: 22, lineLimit: 2)
.frame(maxWidth: 218, maxHeight: 72)
CustomizedText(text: "ここではワーク情報をお届けします。n 最新のワークを探していますのでお待ちください。", tracking: 1.2, frameHeight: 42, fontFamily: "HiraginoSans-W3", fontFamilySize: 12, lineLimit: 2).frame(maxWidth: 333, maxHeight: 42)
Spacer().frame(maxHeight: 210)

}
}
}
}


最新更新