问题: 我试图通过不使用12次相同的MonthView()而是循环使用来使本示例https://swiftui-lab.com/communicating-with-the-view-tree-part-1/更快一些。 不幸的是,当点击标签/月时,变量activeIdx不会被更新,我也不知道为什么... 我的问题是:我该如何更改绑定有效的代码? 预期的行为: 当您点击月份名称时,红色边框应标记您所点击的标签。
import SwiftUI
let months : [String] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
struct ContentView : View {
@State private var activeIdx: Int = 0
var groupedGroupedViews : [[MonthView]] = []
init() {
var groupedViews : [MonthView] = []
for idx in 0..<months.count {
print(idx)
groupedViews.append(MonthView(activeMonth: self.$activeIdx, label: months[idx], idx: idx))
print(months[idx])
if (idx + 1) % 4 == 0 {
groupedGroupedViews.append(groupedViews)
groupedViews = []
}
}
groupedGroupedViews.append(groupedViews)
}
var body: some View {
VStack {
ForEach (groupedGroupedViews, id: \.self) { groupedViews in
HStack {
ForEach (groupedViews, id: \.idx) { view in
view
}
}
}
}
}
}
struct MonthView: View, Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(idx)
}
static func == (lhs: MonthView, rhs: MonthView) -> Bool {
return lhs.idx == rhs.idx
}
@Binding var activeMonth: Int
let label: String
var idx: Int
var body: some View {
Text(label)
.padding(10)
.onTapGesture {
print(self.idx, " tapped")
self.activeMonth = self.idx
print("active = ", self.activeMonth)
}
.background(MonthBorder(show: activeMonth == idx))
}
}
struct MonthBorder: View {
let show: Bool
var body: some View {
RoundedRectangle(cornerRadius: 15)
.stroke(lineWidth: 3.0).foregroundColor(show ? Color.red : Color.clear)
.animation(.easeInOut(duration: 0.6))
}
}
答案 0 :(得分:1)
原因是您不能init
这样的绑定视图。
var myView : MonthView!
init() {
myView = MonthView(activeMonth: self.$activeIdx, label: months[0], idx: 1)
}
var body: some View {
myView}
如果运行上面的代码,您仍然可以看到activeMonth
没有变化。
我认为init()主要是一些UIKit功能的桥梁,不应作为SwiftUI的主要方式。跨平台是必要的,但请尽量避免。请欣赏swiftUI的设计优点,而不是传统实现的开销。
一个简单的答案是将init
移至View。达到您所需的相同功能。
var body: some View {
let groupedGroupedViews : [[MonthView]] = {
var groupedGroupedViews : [[MonthView]] = []
var groupedViews : [MonthView] = []
for idx in 0..<months.count {
print(idx)
groupedViews.append( MonthView(activeMonth: self.$activeIdx, label: months[idx], idx: idx))
print(months[idx])
if (idx + 1) % 4 == 0 {
groupedGroupedViews += [groupedViews]
groupedViews.removeAll()
}
}
groupedGroupedViews += [groupedViews]
return groupedGroupedViews
}()
return VStack {
ForEach (groupedGroupedViews, id: \.self) { groupedView in
HStack {
ForEach (groupedView, id: \.idx) { view in
view
}
}
}
}
}
答案 1 :(得分:0)
我发现了它,多亏了E.Coms,我已经更改了代码,现在它可以工作了。 这是我的解决方案(但我很确定您可以做得更好)
struct ViewValue : Hashable {
var idx: Int
var text: String
}
struct ContentView : View {
@State private var activeIdx: Int = 0
var groupedGroupedValues : [[ViewValue]] = []
init() {
var groupedValues : [ViewValue] = []
for idx in 0..<months.count {
print(idx)
groupedValues.append(ViewValue(idx: idx, text: months[idx]))
print(months[idx])
if (idx + 1) % 4 == 0 {
groupedGroupedValues.append(groupedValues)
groupedValues = []
}
}
groupedGroupedValues.append(groupedValues)
}
var body: some View {
VStack {
ForEach (groupedGroupedValues, id: \.self) { groupedValue in
HStack {
ForEach (groupedValue, id: \.idx) { viewValue in
MonthView(activeMonth: self.$activeIdx, label: viewValue.text, idx: viewValue.idx)
}
}
}
}
}
}