У меня есть вкладка в верхней части экрана. Вкладки - динамические c и ListView () , показанные под вкладкой, зависят от индекса вкладки. Для индекса вкладки 0 ListView () исправлен, но начиная с индекса 1 и далее ListView () будет перезагружаться в зависимости от выбранного индекса вкладки. Итак, моя текущая выбранная вкладка выглядит следующим образом:
@State private var selectedTabIndex = 0
И я перезагружаю View статично, вот так:
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)")
}
}
}
}