stripe-ios
stripe-ios copied to clipboard
[BUG] STPPaymentCardTextFieldDelegate.paymentCardTextFieldDidChange() not called when deleting a character also causes field focus change
Summary
STPPaymentCardTextFieldDelegate.paymentCardTextFieldDidChange does not fire when deleting a character also causes the paymentCardTextFieldDigBeginEditing... function to get called.
Code to reproduce
Just hook up an STPPaymentCardTextFieldDelegate implementation to STPPaymentCardTextField and set breakpoints on all the methods.
iOS version
All
Installation method
Carthage
SDK version
v23.2.0, but I looked at the release notes for newer versions and did not see anything mentioned that looked like it would affect this
Other information
I have uploaded a recording of an app showing this behavior... The app displays a running log of output anytime one of the methods in STPPaymentCardTextFieldDelegate gets called. Whenever a character is deleted, a line beginning with "CardDetails Changed" is logged. Whenever fields gain and lose focus, appropriate lines are also logged.
In the video, I enter a valid card number and the focus automatically moves to the expiration field. I then hit the back/delete key and the following happens:
- Focus moves from the expiration field to the number field
- Field focus lines are logged
- The last number of the credit card is removed
- There is no Card Details Changed log corresponding to that deleted character
- I delete a second character and only then do I get a Card Details Changed log event
The video doesn't show it, but this happens for every field
https://user-images.githubusercontent.com/4357444/232624934-758cadb1-0a88-48e6-b4ad-c5ec1fb92a9a.mov
Hi @magouyaware, I cannot repro this in our example app. Are you using SwiftUI by any chance? I've seen a report similar to yours but it was exclusive to SwiftUI
I am not using SwiftUI. I'll see if I can cobble together a quick sample app I can share with you. Our use case is a little different than most... We have an SDK that is written on top of the Stripe SDK.
On Fri, Apr 21, 2023, 9:59 AM eurias-stripe @.***> wrote:
Hi @magouyaware https://github.com/magouyaware, I cannot repro this in our example app. Are you using SwiftUI by any chance? I've seen a report similar to yours but it was exclusive to SwiftUI
— Reply to this email directly, view it on GitHub https://github.com/stripe/stripe-ios/issues/2483#issuecomment-1518035360, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBH2RF77JDQPJPT2YATACTXCKVFHANCNFSM6AAAAAAXBZ2HDM . You are receiving this because you were mentioned.Message ID: @.***>
Didn't want this to get stale... I've started working on a sample app I can share and hope to have that sometime this week.
@eurias-stripe Ok, I've attached a little sample project, as well as a video clearly showing that any time the back button is pressed, the STPPaymentCardTextFieldDelegate.paymentCardTextFieldDidChange() callback is not called.
It's a very basic and simple app... All code is in ViewController.swift. The entire app consists of an STPPaymentCardTextField instance, a log output area, and a button to clear the log output. Every time STPPaymentCardTextFieldDelegate.paymentCardTextFieldDidChange() is called, a Changed! entry is appended to the log.
Sample Project To run:
- Download and extract the StripeTest.zip
- Run
carthage-bootstrap.shfrom the command line to download and build the Stripe dependencies - Open the Xcode project and run the app
Video Recording The recording starts with data in every field. When I press the back button, the Changed! output gets added to the log every time, with the exception of when the back button press also results in changing fields.
To make this stand out, I clear the log before pressing the back button every time an empty field is focused. https://github.com/stripe/stripe-ios/assets/4357444/12162a95-7fd8-43f4-b6bb-5a55d7554f58
@eurias-stripe Any update on this? I'm making some changes in our code and this is becoming problematic for me
@eurias-stripe I was doing a little more digging today because this issue just became a higher priority because it's preventing me from adding some new features in my app...
When this happens the UI is actually getting out of sync with the backing viewmodel. This happens for every single field, but as an example, here is what happens in the case of the card number field:
- I enter
4242424242424242into the card number field - The cursor auto-advances to the expiration field.
- I then press the delete or backspace key
- The cursor moves back to the card number field and then the last digit (
2) is deleted - The card number field now displays
424242424242424 - However: If I then query the cardNumber property, I will get the full
4242424242424242number as if the last2was still visible in the UI
@eurias-stripe Just noticed the fix for this! Thank you!!!
@eurias-stripe Just tested the latest version of the Stripe iOS SDK, and your fix only partially solved the problem. The paymentCardTextFieldDidChange() callback does indeed now get called, but the cardNumber property is out of sync with the UI, as I mentioned in my last comment before I noticed you had pushed a fix.
As a result, I am still blocked with releasing the next version of our SDK, which is built on top of your SDK. I will update the sample project I already uploaded to show the problem. If you would like me to file a different issue I'm happy to do so, but it is still an issue related to typing the back/delete button on an empty field... the UI has a deleted character from the previous field but the backing model doesn't get updated. Since that backing model doesn't get updated my custom logic for displaying error messages is still incorrect... an error message will not be shown when it should be, because according to the model, the data is actually valid. But according to the UI, the data is invalid.
@eurias-stripe I'm uploading a new sample project that shows that the fix didn't fully fix the problem, and in actuality, is probably not the correct fix to make... The real problem is that, for some reason, formTextFieldDidChange() is not called when pressing the back/delete character causes the focus to move to the previous field.
Once I have a fully entered card number, I can trick the component into thinking it has a fully valid card number when in actuality the card number field is empty. I can do this by doing the following:
- Enter a full card number, which causes the cursor to advance to the expiration field
- Press the back/delete character once, which moves the cursor to the card number field and deletes the last number in the card number field (but does not update the viewmodel)
- Manually click into the expiration field
- Repeat steps 2 and 3 until the card number field is empty
Though the sample project I'm uploading only logs the card number, I've tested this with every single field, and the behavior is the same for each field.
Here is the new sample project: StripeTest-New.zip
Here are some videos and screenshots:
https://github.com/stripe/stripe-ios/assets/4357444/a117bc66-1125-40f2-a3be-8e43034005fe
https://github.com/stripe/stripe-ios/assets/4357444/8a22f1ae-f512-4195-b53b-5b5b612dfe77
@magouyaware It looks like this was fixed in 23.17.2: I can't reproduce the issue using your sample app. Closing this issue, but feel free to reopen or file a new one if the behavior still seems incorrect!