swiftui中uitextfield的默认值
我已经尝试将货币Textfield实施到我的项目上,我在此网站上找到了它 - https:/https:// /benoitpasquier.com/currency-textfield-in-swiftui 。
它几乎可以按预期工作,但是有一个主要问题:传递的价值并未出现在Textfield中。 (例如,绑定= 1000在Textfield中仍以$ 0.00的形式显示)
代码下面:
import Foundation
import SwiftUI
import UIKit
class CurrencyUITextField: UITextField {
@Binding private var value: Int
private let formatter: NumberFormatterProtocol
init(formatter: NumberFormatterProtocol, value: Binding<Int>) {
self.formatter = formatter
self._value = value
super.init(frame: .zero)
setupViews()
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: superview)
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
addTarget(self, action: #selector(resetSelection), for: .allTouchEvents)
keyboardType = .numberPad
textAlignment = .right
sendActions(for: .editingChanged)
}
override func removeFromSuperview() {
Log.info("Removed CurrencyTextField from View")
}
override func deleteBackward() {
text = textValue.digits.dropLast().string
sendActions(for: .editingChanged)
}
private func setupViews() {
tintColor = .clear
font = .systemFont(ofSize: 40, weight: .regular)
}
@objc private func editingChanged() {
text = currency(from: decimal)
resetSelection()
updateValue()
}
@objc private func resetSelection() {
selectedTextRange = textRange(from: endOfDocument, to: endOfDocument)
}
private func updateValue() {
DispatchQueue.main.async { [weak self] in
self?.value = self?.intValue ?? 0
}
}
private var textValue: String {
return text ?? ""
}
private var decimal: Decimal {
return textValue.decimal / pow(10, formatter.maximumFractionDigits)
}
private var intValue: Int {
return NSDecimalNumber(decimal: decimal * 100).intValue
}
private func currency(from decimal: Decimal) -> String {
return formatter.string(for: decimal) ?? ""
}
}
extension StringProtocol where Self: RangeReplaceableCollection {
var digits: Self { filter(\.isWholeNumber) }
}
extension String {
var decimal: Decimal { Decimal(string: digits) ?? 0 }
}
extension LosslessStringConvertible {
var string: String { .init(self) }
}
import SwiftUI
import UIKit
struct CurrencyTextField: View {
@Binding var value: Int
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 15)
.foregroundColor(.quaternary)
.frame(maxHeight: 80)
CurrencyTextField_(numberFormatter: NumberFormatter.currencyFormatter, value: $value)
.padding(.horizontal)
}
.frame(maxHeight: 80)
}
}
struct CurrencyTextField_: UIViewRepresentable {
typealias UIViewType = CurrencyUITextField
let numberFormatter: NumberFormatterProtocol
let currencyField: CurrencyUITextField
init(numberFormatter: NumberFormatterProtocol, value: Binding<Int>) {
self.numberFormatter = numberFormatter
currencyField = CurrencyUITextField(formatter: numberFormatter, value: value)
}
func makeUIView(context: Context) -> CurrencyUITextField {
return currencyField
}
func updateUIView(_ uiView: CurrencyUITextField, context: Context) {}
}
struct CurrencyTextField_Previews: PreviewProvider {
static var previews: some View {
CurrencyTextField(value: .constant(1025))
}
}
此视图可以以量= 0初始化,也可以以“编辑”视图(例如1000,以前由同一crurnertextfield创建)的“编辑”视图(例如1000) )
struct CreateTransactionView: View {
@State var amount = 0
var body: some View {
VStack(alignment: .leading, spacing: 15) {
CurrencyTextField(value: $amount)
}
}
}
可能导致这个问题是什么? PS。我对Uikit几乎没有经验。
I've tried to implement Currency TextField to my project, which I found on this website - https://benoitpasquier.com/currency-textfield-in-swiftui.
It almost does work as expected, but with one major issue: passed value is not showing up in TextField. (eg. Binding = 1000 is still presented as $0.00 in TextField)
Code below:
import Foundation
import SwiftUI
import UIKit
class CurrencyUITextField: UITextField {
@Binding private var value: Int
private let formatter: NumberFormatterProtocol
init(formatter: NumberFormatterProtocol, value: Binding<Int>) {
self.formatter = formatter
self._value = value
super.init(frame: .zero)
setupViews()
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: superview)
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
addTarget(self, action: #selector(resetSelection), for: .allTouchEvents)
keyboardType = .numberPad
textAlignment = .right
sendActions(for: .editingChanged)
}
override func removeFromSuperview() {
Log.info("Removed CurrencyTextField from View")
}
override func deleteBackward() {
text = textValue.digits.dropLast().string
sendActions(for: .editingChanged)
}
private func setupViews() {
tintColor = .clear
font = .systemFont(ofSize: 40, weight: .regular)
}
@objc private func editingChanged() {
text = currency(from: decimal)
resetSelection()
updateValue()
}
@objc private func resetSelection() {
selectedTextRange = textRange(from: endOfDocument, to: endOfDocument)
}
private func updateValue() {
DispatchQueue.main.async { [weak self] in
self?.value = self?.intValue ?? 0
}
}
private var textValue: String {
return text ?? ""
}
private var decimal: Decimal {
return textValue.decimal / pow(10, formatter.maximumFractionDigits)
}
private var intValue: Int {
return NSDecimalNumber(decimal: decimal * 100).intValue
}
private func currency(from decimal: Decimal) -> String {
return formatter.string(for: decimal) ?? ""
}
}
extension StringProtocol where Self: RangeReplaceableCollection {
var digits: Self { filter(\.isWholeNumber) }
}
extension String {
var decimal: Decimal { Decimal(string: digits) ?? 0 }
}
extension LosslessStringConvertible {
var string: String { .init(self) }
}
import SwiftUI
import UIKit
struct CurrencyTextField: View {
@Binding var value: Int
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 15)
.foregroundColor(.quaternary)
.frame(maxHeight: 80)
CurrencyTextField_(numberFormatter: NumberFormatter.currencyFormatter, value: $value)
.padding(.horizontal)
}
.frame(maxHeight: 80)
}
}
struct CurrencyTextField_: UIViewRepresentable {
typealias UIViewType = CurrencyUITextField
let numberFormatter: NumberFormatterProtocol
let currencyField: CurrencyUITextField
init(numberFormatter: NumberFormatterProtocol, value: Binding<Int>) {
self.numberFormatter = numberFormatter
currencyField = CurrencyUITextField(formatter: numberFormatter, value: value)
}
func makeUIView(context: Context) -> CurrencyUITextField {
return currencyField
}
func updateUIView(_ uiView: CurrencyUITextField, context: Context) {}
}
struct CurrencyTextField_Previews: PreviewProvider {
static var previews: some View {
CurrencyTextField(value: .constant(1025))
}
}
This view can be initialised with amount = 0, or as an 'Edit' view, with injected amount value (eg. 1000, previously created by the same CurrencyTextField)
struct CreateTransactionView: View {
@State var amount = 0
var body: some View {
VStack(alignment: .leading, spacing: 15) {
CurrencyTextField(value: $amount)
}
}
}
What could be possibly causing this issue?
PS. I have little to no experience with UIKit.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以通过更改仅适用于iOS 15+的格式来使用
textfield
中的货币。或使用
locale
You can use currency in
TextField
by changing the format which is only available for iOS 15+.or using
Locale
UpdateUiview
尚未实现。makeuiview
无法正确完成。MakeUiview应在本地启动Uiview并将其返回。
updateUIView
hasn't been implemented. AndmakeUIView
isn't done correctly.makeUIView should init the UIView locally and return it.