Skip to content

Commit 6e79aad

Browse files
committed
Added BindableTextField to overcome iOS15 regresion with TextField
1 parent 456bc5f commit 6e79aad

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

WooCommerce/Classes/ViewRelated/Orders/Simple Payments/Amount/SimplePaymentsAmount.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ struct SimplePaymentsAmount: View {
9999
.secondaryBodyStyle()
100100

101101
// Amount Textfield
102-
TextField(viewModel.amountPlaceholder, text: $viewModel.amount)
102+
BindableTextfield(viewModel.amountPlaceholder, text: $viewModel.amount)
103103
.font(.system(size: Layout.amountFontSize(scale: scale), weight: .bold, design: .default))
104104
.foregroundColor(Color(.text))
105105
.multilineTextAlignment(.center)

WooCommerce/Classes/ViewRelated/Orders/Simple Payments/Amount/SimplePaymentsAmountViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Yosemite
55
///
66
final class SimplePaymentsAmountViewModel: ObservableObject {
77

8-
/// Stores amount entered by the merchant.
8+
/// Stores the amount(formatted) entered by the merchant.
99
///
1010
@Published var amount: String = "" {
1111
didSet {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import Foundation
2+
import SwiftUI
3+
4+
/// `UITextfield` wrapper reads and writes to provided binding value.
5+
/// Needed because iOS 15 won't allow us to intercept correctly the binding value in the original `SwiftUI` component.
6+
/// Feel free to add modifiers as it is needed.
7+
///
8+
struct BindableTextfield: UIViewRepresentable {
9+
10+
/// Placeholder of the textfield.
11+
///
12+
let placeHolder: String?
13+
14+
/// Binding to read content from and write content to.
15+
///
16+
@Binding var text: String
17+
18+
init(_ placeholder: String?, text: Binding<String>) {
19+
self.placeHolder = placeholder
20+
self._text = text
21+
}
22+
23+
/// Creates view with the initial configuration.
24+
///
25+
func makeUIView(context: Context) -> UITextField {
26+
let textfield = UITextField()
27+
textfield.placeholder = placeHolder
28+
textfield.delegate = context.coordinator
29+
return textfield
30+
}
31+
32+
/// Creates coordinator.
33+
///
34+
func makeCoordinator() -> Coordinator {
35+
Coordinator(_text)
36+
}
37+
38+
/// Updates underlying view.
39+
///
40+
func updateUIView(_ uiView: UITextField, context: Context) {
41+
uiView.text = text
42+
}
43+
}
44+
45+
// MARK: Coordinator
46+
47+
extension BindableTextfield {
48+
/// Coordinator needed to listen to the `TextField` delegate and relay the input content to the binding value.
49+
///
50+
final class Coordinator: NSObject, UITextFieldDelegate {
51+
52+
/// Binding to set content from the `TextField` delegate.
53+
///
54+
@Binding var text: String
55+
56+
init(_ text: Binding<String>) {
57+
self._text = text
58+
}
59+
60+
/// Relays the input value to the binding variable.
61+
///
62+
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
63+
if let currentInput = textField.text, let inputRange = Range(range, in: currentInput) {
64+
text = currentInput.replacingCharacters(in: inputRange, with: string)
65+
} else {
66+
text = string
67+
}
68+
return false
69+
}
70+
}
71+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@
452452
26B119C224D1CD3500FED5C7 /* WooConstantsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B119C124D1CD3500FED5C7 /* WooConstantsTests.swift */; };
453453
26B3D8A0252235C50054C319 /* RefundShippingDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B3D89F252235C50054C319 /* RefundShippingDetailsViewModel.swift */; };
454454
26B3EC622744772A0075EAE6 /* SimplePaymentsSummaryViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B3EC612744772A0075EAE6 /* SimplePaymentsSummaryViewModelTests.swift */; };
455+
26B3EC642745916F0075EAE6 /* BindableTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B3EC632745916F0075EAE6 /* BindableTextField.swift */; };
455456
26B98758273C5BE30090E8CA /* EditCustomerNoteViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B98757273C5BE30090E8CA /* EditCustomerNoteViewModelProtocol.swift */; };
456457
26B9875D273C6A830090E8CA /* SimplePaymentsNoteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B9875C273C6A830090E8CA /* SimplePaymentsNoteViewModel.swift */; };
457458
26B9875F273CB6AA0090E8CA /* SimplePaymentsNoteViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B9875E273CB6AA0090E8CA /* SimplePaymentsNoteViewModelTests.swift */; };
@@ -1929,6 +1930,7 @@
19291930
26B119C124D1CD3500FED5C7 /* WooConstantsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooConstantsTests.swift; sourceTree = "<group>"; };
19301931
26B3D89F252235C50054C319 /* RefundShippingDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundShippingDetailsViewModel.swift; sourceTree = "<group>"; };
19311932
26B3EC612744772A0075EAE6 /* SimplePaymentsSummaryViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsSummaryViewModelTests.swift; sourceTree = "<group>"; };
1933+
26B3EC632745916F0075EAE6 /* BindableTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableTextField.swift; sourceTree = "<group>"; };
19321934
26B98757273C5BE30090E8CA /* EditCustomerNoteViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditCustomerNoteViewModelProtocol.swift; sourceTree = "<group>"; };
19331935
26B9875C273C6A830090E8CA /* SimplePaymentsNoteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsNoteViewModel.swift; sourceTree = "<group>"; };
19341936
26B9875E273CB6AA0090E8CA /* SimplePaymentsNoteViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsNoteViewModelTests.swift; sourceTree = "<group>"; };
@@ -4620,6 +4622,7 @@
46204622
26C6E8E926E8FD3900C7BB0F /* LazyView.swift */,
46214623
26C6E8EB26E8FF4800C7BB0F /* LazyNavigationLink.swift */,
46224624
AE6DBE3A2732CAAD00957E7A /* AdaptiveStack.swift */,
4625+
26B3EC632745916F0075EAE6 /* BindableTextField.swift */,
46234626
);
46244627
path = "SwiftUI Components";
46254628
sourceTree = "<group>";
@@ -8257,6 +8260,7 @@
82578260
02F843DA273646A30017FE12 /* JetpackBenefitsBanner.swift in Sources */,
82588261
027D4A8D2526FD1800108626 /* SettingsViewController.swift in Sources */,
82598262
02E262C9238D0AD300B79588 /* ProductStockStatusListSelectorCommand.swift in Sources */,
8263+
26B3EC642745916F0075EAE6 /* BindableTextField.swift in Sources */,
82608264
CE2A9FC823C3D2D4002BEC1C /* RefundedProductsDataSource.swift in Sources */,
82618265
5783FB3F25D7369F00B9984B /* WooAnalyticsEventPropertyType.swift in Sources */,
82628266
CECC759523D6057E00486676 /* OrderItem+Woo.swift in Sources */,

0 commit comments

Comments
 (0)