SwiftUI:具有计算 属性 的 ObservableObject
SwiftUI: ObservableObject with a computed property
我有一个带有自定义月份选择器的简单视图。每次您向左或向右单击人字形时,
在 DateView 内部我有两个私有变量:startDateOfMonth2: Date 和 endDateOfMonth2: Date。但它们仅在 DateView 中可用。
问题
如何使这两个变量在其他视图中可用?
我尝试将它们添加为@Published 变量,但出现错误:
Property wrapper cannot be applied to a computed property
我发现了几个类似的问题,但我无法在我的代码中使用它们的答案。
import SwiftUI
class SelectedDate: ObservableObject {
@Published var selectedMonth: Date = Date()
@Published var startDateOfMonth2: Date {
let components = Calendar.current.dateComponents([.year, .month], from: selectedMonth)
let startOfMonth = Calendar.current.date(from: components)!
return startOfMonth
}
@Published var endDateOfMonth2: Date {
var components = Calendar.current.dateComponents([.year, .month], from: selectedMonth)
components.month = (components.month ?? 0) + 1
let endOfMonth = Calendar.current.date(from: components)!
return endOfMonth
}
}
struct DateView: View {
@EnvironmentObject var selectedDate: SelectedDate
static let dateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.setLocalizedDateFormatFromTemplate("yyyy MMMM")
return formatter
}()
var body: some View {
HStack {
Image(systemName: "chevron.left")
.frame(width: 50, height: 50)
.contentShape(Rectangle())
.onTapGesture {
self.changeMonthBy(-1)
}
Spacer()
Text("\(selectedDate.selectedMonth, formatter: Self.dateFormat)")
Spacer()
Image(systemName: "chevron.right")
.frame(width: 50, height: 50)
.contentShape(Rectangle())
.onTapGesture {
self.changeMonthBy(1)
}
}
.padding(EdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5))
.background(Color.yellow)
}
func changeMonthBy(_ months: Int) {
if let selectedMonth = Calendar.current.date(byAdding: .month, value: months, to: selectedDate.selectedMonth) {
self.selectedDate.selectedMonth = selectedMonth
}
}
}
无需将您的计算值声明为已发布,因为它们取决于已发布的值。当发布的值发生变化时,它们会重新计算。
class SelectedDate: ObservableObject {
@Published var selectedMonth: Date = Date()
var startDateOfMonth2: Date {
let components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
let startOfMonth = Calendar.current.date(from: components)!
print(startOfMonth)
return startOfMonth
}
var endDateOfMonth2: Date {
var components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
components.month = (components.month ?? 0) + 1
let endOfMonth = Calendar.current.date(from: components)!
print(endOfMonth)
return endOfMonth
}
}
当您点击打印 endDateOfMonth2
时,您会看到它正在发生变化。
computed 属性 基本上是函数。
它不能存储值,它只是从其他变量或 属性 在 getter 中计算值并将值更新回它在 setter 中计算的值。
仔细想想你属性的性格。
大多数情况下,你可以直接读写计算属性。
请记住它是功能核心和 属性 皮肤
我有一个带有自定义月份选择器的简单视图。每次您向左或向右单击人字形时,
在 DateView 内部我有两个私有变量:startDateOfMonth2: Date 和 endDateOfMonth2: Date。但它们仅在 DateView 中可用。
问题
如何使这两个变量在其他视图中可用?
我尝试将它们添加为@Published 变量,但出现错误:
Property wrapper cannot be applied to a computed property
我发现了几个类似的问题,但我无法在我的代码中使用它们的答案。
import SwiftUI
class SelectedDate: ObservableObject {
@Published var selectedMonth: Date = Date()
@Published var startDateOfMonth2: Date {
let components = Calendar.current.dateComponents([.year, .month], from: selectedMonth)
let startOfMonth = Calendar.current.date(from: components)!
return startOfMonth
}
@Published var endDateOfMonth2: Date {
var components = Calendar.current.dateComponents([.year, .month], from: selectedMonth)
components.month = (components.month ?? 0) + 1
let endOfMonth = Calendar.current.date(from: components)!
return endOfMonth
}
}
struct DateView: View {
@EnvironmentObject var selectedDate: SelectedDate
static let dateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.setLocalizedDateFormatFromTemplate("yyyy MMMM")
return formatter
}()
var body: some View {
HStack {
Image(systemName: "chevron.left")
.frame(width: 50, height: 50)
.contentShape(Rectangle())
.onTapGesture {
self.changeMonthBy(-1)
}
Spacer()
Text("\(selectedDate.selectedMonth, formatter: Self.dateFormat)")
Spacer()
Image(systemName: "chevron.right")
.frame(width: 50, height: 50)
.contentShape(Rectangle())
.onTapGesture {
self.changeMonthBy(1)
}
}
.padding(EdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5))
.background(Color.yellow)
}
func changeMonthBy(_ months: Int) {
if let selectedMonth = Calendar.current.date(byAdding: .month, value: months, to: selectedDate.selectedMonth) {
self.selectedDate.selectedMonth = selectedMonth
}
}
}
无需将您的计算值声明为已发布,因为它们取决于已发布的值。当发布的值发生变化时,它们会重新计算。
class SelectedDate: ObservableObject {
@Published var selectedMonth: Date = Date()
var startDateOfMonth2: Date {
let components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
let startOfMonth = Calendar.current.date(from: components)!
print(startOfMonth)
return startOfMonth
}
var endDateOfMonth2: Date {
var components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
components.month = (components.month ?? 0) + 1
let endOfMonth = Calendar.current.date(from: components)!
print(endOfMonth)
return endOfMonth
}
}
当您点击打印 endDateOfMonth2
时,您会看到它正在发生变化。
computed 属性 基本上是函数。 它不能存储值,它只是从其他变量或 属性 在 getter 中计算值并将值更新回它在 setter 中计算的值。 仔细想想你属性的性格。 大多数情况下,你可以直接读写计算属性。 请记住它是功能核心和 属性 皮肤