Adyen / adyen-ios

Adyen iOS Drop-in and Components
https://docs.adyen.com/checkout/ios
MIT License
151 stars 121 forks source link

[BUG] crash: [Adyen.SearchViewController setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchField #1167

Closed dragomir-ivanov-212 closed 1 year ago

dragomir-ivanov-212 commented 1 year ago

Describe the bug Attempting to checkout with an IssuerListComponent (dotpay, ideal, onlineBanking_PL) using AdyenDropIn (UIKit) leads to a crash.

Crash on ModalViewController.swift:131

Thread 1: "[<Adyen.SearchViewController 0x294132e00> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchField."

To Reproduce Steps to reproduce the behavior:

  1. setup a DropInComponent with a single "issuer list" payment method (e.g. ideal) and allowsSkippingPaymentList=true
  2. present via present(dropInComponent.viewController, animated: true)

Expected behavior I expect no crashes and a normal checkout process.

Screenshots none

Smartphone (please complete the following information):

Additional context

PODS:

  - Adyen (5.1.0):
    - Adyen/Actions (= 5.1.0)
    - Adyen/Card (= 5.1.0)
    - Adyen/Components (= 5.1.0)
    - Adyen/Core (= 5.1.0)
    - Adyen/DropIn (= 5.1.0)
    - Adyen/Encryption (= 5.1.0)
    - Adyen/Session (= 5.1.0)
  - Adyen/Actions (5.1.0):
    - Adyen/Core
    - Adyen3DS2 (= 2.3.0)
  - Adyen/Card (5.1.0):
    - Adyen/Core
    - Adyen/Encryption
  - Adyen/Components (5.1.0):
    - Adyen/Core
    - Adyen/Encryption
  - Adyen/Core (5.1.0):
    - AdyenNetworking (= 1.0.0)
  - Adyen/DropIn (5.1.0):
    - Adyen/Actions
    - Adyen/Card
    - Adyen/Components
    - Adyen/Core
    - Adyen/Encryption
  - Adyen/Encryption (5.1.0)
  - Adyen/Session (5.1.0):
    - Adyen/Actions
    - Adyen/Core
  - Adyen3DS2 (2.3.0)
  - AdyenNetworking (1.0.0)

stacktrace:

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread:  0

Last Exception Backtrace:
0   CoreFoundation                         0x18040e7e0 __exceptionPreprocess + 160
1   libobjc.A.dylib                        0x180051144 objc_exception_throw + 56
2   CoreFoundation                         0x18040e4fc -[NSException init] + 0
3   Foundation                             0x180b5205c -[NSObject(NSKeyValueCoding) setValue:forKey:] + 308
4   UIKitCore                              0x117be76a0 -[UIViewController setValue:forKey:] + 76
5   UIKitCore                              0x117ef0984 -[UIRuntimeOutletConnection connect] + 80
6   CoreFoundation                         0x1803f8994 -[NSArray makeObjectsPerformSelector:] + 192
7   UIKitCore                              0x117ee878c -[UINib instantiateWithOwner:options:] + 1408
8   UIKitCore                              0x117bee028 -[UIViewController loadView] + 392
9   UIKitCore                              0x117bee2b0 -[UIViewController loadViewIfRequired] + 96
10  UIKitCore                              0x117bee800 -[UIViewController view] + 20
11  trading212-feature                     0x1052bfc04 closure #1 in ModalViewController.stackView.getter + 168 (ModalViewController.swift:131)
12  trading212-feature                     0x1052be460 ModalViewController.stackView.getter + 164 (ModalViewController.swift:130)
13  trading212-feature                     0x1052be2fc ModalViewController.addChildViewController() + 368 (ModalViewController.swift:67)
14  trading212-feature                     0x1052be098 ModalViewController.viewDidLoad() + 128 (ModalViewController.swift:60)
15  trading212-feature                     0x1052be3a4 @objc ModalViewController.viewDidLoad() + 36
16  UIKitCore                              0x117bea7ec -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 80
17  UIKitCore                              0x117bee514 -[UIViewController loadViewIfRequired] + 708
18  UIKitCore                              0x117bee800 -[UIViewController view] + 20
19  trading212-feature                     0x10541ae50 WrapperViewController.setupChildViewController() + 328 (WrapperViewController.swift:56)
20  trading212-feature                     0x10541acdc WrapperViewController.init(child:) + 392 (WrapperViewController.swift:29)
21  trading212-feature                     0x10541ab44 WrapperViewController.__allocating_init(child:) + 40
22  trading212-feature                     0x1051d2c40 DropInNavigationController.wrapInModalController(component:isRoot:) + 580 (DropInNavigationController.swift:94)
23  trading212-feature                     0x1051d1ffc DropInNavigationController.setup(root:) + 68 (DropInNavigationController.swift:100)
24  trading212-feature                     0x1051d1f6c DropInNavigationController.init(rootComponent:style:cancelHandler:) + 468 (DropInNavigationController.swift:37)
25  trading212-feature                     0x1051d1d88 DropInNavigationController.__allocating_init(rootComponent:style:cancelHandler:) + 72
26  trading212-feature                     0x1051ada44 DropInComponent.navigationController.getter + 472 (DropInComponent.swift:170)
27  trading212-feature                     0x1051ad860 DropInComponent.viewController.getter + 28 (DropInComponent.swift:82)

I see a _nibName = 0x000060000377cf20 "SearchView" on SearchViewController which might explain this.

partial (relevant) dump(self) of ModalViewController

(Adyen.ModalViewController) $R1 = 0x00000001307b6200 {
  UIKit.UIViewController = {
    baseUIResponder@0 = {
      baseNSObject@0 = {
        isa = Adyen.ModalViewController
      }
    }
  ...
  innerController = 0x000000013002f200 {
    UIKit.UIViewController = {
      baseUIResponder@0 = {
        baseNSObject@0 = {
          isa = Adyen.SearchViewController
        }
      }
      _overrideTransitioningDelegate = 0x0000000000000000
      _view = 0x0000000000000000
      _tabBarItem = 0x0000000000000000
      _navigationItem = 0x0000000000000000
      _toolbarItems = 0x0000000000000000
      _title = 0x0000600003eb6130 "Local Polish Payment Methods"
      _nibName = 0x000060000377cf20 "SearchView"
      _nibBundle = 0x00006000010e8cd0 {...}
      _parentViewController = 0x00000001307b6200
      ...
    }
    childViewController = 0x000000029c446a00 {
      UIKit.UITableViewController = {
        baseUIViewController@0 = {
          baseUIResponder@0 = {
            baseNSObject@0 ={...}
          }
        }
      }
      ...
}
erenbesel commented 1 year ago

Hey @dragomir-ivanov-212 thanks for reporting this. We will investigate as soon as possible.

I imagine it's not new to v5.1.0. We will get back to you when we have an update!

dragomir-ivanov-212 commented 1 year ago

Thank you for the fast response! I just tried to reproduce this using the provided demo app, and it doesn't reproduce.

I tracked down a SearchView.xib in the parent app that is integrating DropInComponent. There appears to be a naming clash. I'll try to resolve the naming clash and get back to you.

erenbesel commented 1 year ago

Ah nice! Yeah that would be a reason indeed. Let us know the result, thanks!

AshrafJaddo commented 1 year ago

We also found the same issue with another xib, ModalViewContainer.xib that our App has and was causing a crash when launching Adyen.

Adyen team should use Bundle.module to force binding the correct xib or prefix their classes to avoid this common issue in SPM.

erenbesel commented 1 year ago

Hey @AshrafJaddo, Hmm I see. But we are already doing so, e.g. in ModalViewController line 44, super.init(nibName: nil, bundle: Bundle(for: ModalViewController.self))

Are you referring to another usage?

On another note, we realize some of the names like this one could have potential collusions and we will keep improving them as we encounter them.

AshrafJaddo commented 1 year ago

Hi, not sure but in our App get this error when we try to launch the payment view controller, we fixed by renaming our ModalViewController.xib to something else.

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AdyenDropIn.ModalViewController 0x61900006c780> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key containerView.'

dragomir-ivanov-212 commented 1 year ago

@erenbesel I'm pleased to say that renaming the offending view in the main app fixed the crash.

Since @AshrafJaddo also chimed in with much the same problem, do we consider this issue "fixed", or will you look into it further?

AshrafJaddo commented 1 year ago

I think the Adyen team should either use prefixes or load the resources via the module API. names like SearchViewContainer, ModalVC, ContainerVC ..etc are common an a lot of Apps has them.

erenbesel commented 1 year ago

We agree these names can be problematic, thankfully it's not many of them. On a side note, we did not expect this issue to resurface after the change to load these controllers with the bundle of its own module. (previously bundle was nil).

We will still be on the lookout for renaming if possible. Closing this one for now, thanks all!