我在一个金钱输入屏幕上工作,我需要实现一个自定义init来根据初始化的金额设置一个状态变量。
我认为以下方法可以奏效:
struct AmountView : View {
@Binding var amount: Double
@State var includeDecimal = false
init(amount: Binding<Double>) {
self.amount = amount
self.includeDecimal = round(amount)-amount > 0
}
}
然而,这给了我一个编译器错误如下:
不能将类型为“Binding”的值分配给类型为“Double”的值
我如何实现一个自定义init方法,在一个绑定结构?
你说(在评论中)“我需要能够改变includeDecimal”。改变includeDecimal意味着什么?显然,您希望根据amount(初始化时)是否为整数来初始化它。好的。如果includeDecimal为假,然后你把它改成真,会发生什么?你是否会迫使数量变成非整数?
总之,你不能在init中修改includeDecimal。但是你可以在init中初始化它,像这样:
struct ContentView : View {
@Binding var amount: Double
init(amount: Binding<Double>) {
$amount = amount
$$includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
}
@State private var includeDecimal: Bool
(注意,在某些时候$$includeDecimal语法将被更改为_includeDecimal。)
你可以用静态函数或者自定义init来实现。
import SwiftUI
import PlaygroundSupport
struct AmountView: View {
@Binding var amount: Double
@State var includeDecimal: Bool
var body: some View {
Text("The amount is \(amount). \n Decimals \(includeDecimal ? "included" : "excluded")")
}
}
extension AmountView {
static func create(amount: Binding<Double>) -> Self {
AmountView(amount: amount, includeDecimal: round(amount.wrappedValue) - amount.wrappedValue > 0)
}
init(amount: Binding<Double>) {
_amount = amount
includeDecimal = round(amount.wrappedValue) - amount.wrappedValue > 0
}
}
struct ContentView: View {
@State var amount1 = 5.2
@State var amount2 = 5.6
var body: some View {
AmountView.create(amount: $amount1)
AmountView(amount: $amount2)
}
}
PlaygroundPage.current.setLiveView(ContentView())
实际上你根本不需要自定义init,因为逻辑可以很容易地移动到. onappear,除非你需要显式地在外部设置初始状态。
struct AmountView: View {
@Binding var amount: Double
@State private var includeDecimal = true
var body: some View {
Text("The amount is \(amount, specifier: includeDecimal ? "%.3f" : "%.0f")")
Toggle("Include decimal", isOn: $includeDecimal)
.onAppear {
includeDecimal = round(amount) - amount > 0
}
}
}
通过这种方式,您可以像文档建议的那样保持@State为私有并在内部初始化。
不要在视图中的点初始化视图的状态属性
实例化视图的层次结构,因为这可能会发生冲突
SwiftUI提供的存储管理。为了避免这种情况,
始终将状态声明为私有,并将其放置在最高视图中
需要访问值的视图层次结构
.
你说(在评论中)“我需要能够改变includeDecimal”。改变includeDecimal意味着什么?显然,您希望根据amount(初始化时)是否为整数来初始化它。好的。如果includeDecimal为假,然后你把它改成真,会发生什么?你是否会迫使数量变成非整数?
总之,你不能在init中修改includeDecimal。但是你可以在init中初始化它,像这样:
struct ContentView : View {
@Binding var amount: Double
init(amount: Binding<Double>) {
$amount = amount
$$includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
}
@State private var includeDecimal: Bool
(注意,在某些时候$$includeDecimal语法将被更改为_includeDecimal。)