Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paywall crashes on iOS when used in a ModalBottomSheet #286

Open
7 of 10 tasks
Stuart-campbell opened this issue Dec 28, 2024 · 4 comments
Open
7 of 10 tasks

Paywall crashes on iOS when used in a ModalBottomSheet #286

Stuart-campbell opened this issue Dec 28, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@Stuart-campbell
Copy link

Stuart-campbell commented Dec 28, 2024

Describe the bug
A clear and concise description of what the bug is. The more detail you can provide the faster our
team will be able to triage and resolve the issue. Do not remove any of the steps from the
template below. If a step is not applicable to your issue, please leave that step empty.

  1. Environment
    1. Platform: iOS
    2. SDK version: 1.3.6+13.13.1
    3. OS version: 17.0
    4. IDE (e.g. Android Studio, Xcode, Fleet): Xcode
    5. IDE version: 15.4
    6. Device and/or emulator/simulator:
      • Device
      • Emulator/simulator
    7. Environment:
      • Closed testing / Sandbox
      • TestFlight
      • Production
    8. How widespread is the issue. Percentage of devices affected. 100%
  2. Debug logs that reproduce the issue
*** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<RCPaywallViewController: 0x10e85d600> should have parent view controller:(null) but actual parent is:<ComposeHostingViewController: 0x10cb1f910>'
*** First throw call stack:
  1. Steps to reproduce, with a description of expected vs. actual behavior
    Attempt to show Paywall when inside a ModalBottomSheet

Works as expected

    val options = remember {
        PaywallOptions(dismissRequest = { }) {
            shouldDisplayDismissButton = true
        }
    }
    Paywall(options)

Crashes

    val options = remember {
        PaywallOptions(dismissRequest = { }) {
            shouldDisplayDismissButton = true
        }
    }
    ModalBottomSheet(onDismissRequest = {}) {
        Paywall(options)
    }
  1. Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to
    have context, eg. stackoverflow, etc.)

Likely a compose multipaltform bug with view interop but thought it was worth raising as showing paywall in this manner feel like a common way to want to show it. I can work around so its not a huge priority to be fixed for me anyway.

Thanks

@Stuart-campbell Stuart-campbell added the bug Something isn't working label Dec 28, 2024
@JayShortway
Copy link
Member

Hi @Stuart-campbell, thanks for reporting this! Just curious, which version of Compose Multiplatform are you using? And may I ask what your workaround is? Thanks in advance!

@sbenmeddour
Copy link

Same issue when trying to display in ModalBottomSheet

Using compose multiplatform 1.7.3

*** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<RCPaywallViewController: 0x109977000> should have parent view controller:(null) but actual parent is:<ComposeHostingViewController: 0x10a111eb0>'
*** First throw call stack:
(
	0   CoreFoundation                      0x00000001804ae0f8 __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x0000000180087db4 objc_exception_throw + 56
	2   CoreFoundation                      0x00000001804ae008 -[NSException initWithCoder:] + 0
	3   UIKitCore                           0x00000001858e231c -[UIView(Hierarchy) _associatedViewControllerForwardsAppearanceCallbacks:performHierarchyCheck:isRoot:] + 216
	4   UIKitCore                           0x00000001858e2aa4 -[UIView(Hierarchy) _willMoveToWindow:withAncestorView:] + 184
	5   UIKitCore                           0x00000001858e35e8 _makeSubTreePerformSelector + 428
	6   UIKitCore                           0x00000001858eff8c -[UIView(Internal) _addSubview:positioned:relativeTo:] + 384
	7   iosApp                              0x000000010326f920 kfun:androidx.compose.ui.viewinterop.UIKitInteropViewControllerHolder#insertInteropView(platform.UIKit.UIView;kotlin.Int){} + 500
	8   iosApp                              0x00000001032d355c kfun:androidx.compose.ui.viewinterop.InteropViewHolder#insertInteropView(platform.UIKit.UIView;kotlin.Int){}-trampoline + 72
	9   iosApp                              0x000000010326a7e8 kfun:androidx.compose.ui.viewinterop.UIKitInteropContainer.place$lambda$2#internal + 196
	10  iosApp                              0x000000010326abf0 kfun:androidx.compose.ui.viewinterop.UIKitInteropContainer.$place$lambda$2$FUNCTION_REFERENCE$2.invoke#internal + 80
	11  iosApp                              0x000000010326ad08 kfun:androidx.compose.ui.viewinterop.UIKitInteropContainer.$place$lambda$2$FUNCTION_REFERENCE$2.$<bridge-DNN>invoke(){}#internal + 72
	12  iosApp                              0x0000000102154704 kfun:kotlin.Function0#invoke(){}1:0-trampoline + 100
	13  iosApp                              0x0000000103298400 kfun:androidx.compose.ui.window.MetalRedrawer.draw$lambda$6#internal + 2984
	14  iosApp                              0x000000010329a2f0 kfun:androidx.compose.ui.window.MetalRedrawer.$draw$lambda$6$FUNCTION_REFERENCE$10.invoke#internal + 100
	15  iosApp                              0x000000010329a4c8 kfun:androidx.compose.ui.window.MetalRedrawer.$draw$lambda$6$FUNCTION_REFERENCE$10.$<bridge-DNN>invoke(){}#internal + 72
	16  iosApp                              0x0000000102154704 kfun:kotlin.Function0#invoke(){}1:0-trampoline + 100
	17  iosApp                              0x00000001032953bc kfun:androidx.compose.ui.window.MetalRedrawer.draw#internal + 7724
	18  iosApp                              0x0000000103297450 kfun:androidx.compose.ui.window.MetalRedrawer.<init>$lambda$1#internal + 444
	19  iosApp                              0x0000000103299d10 kfun:androidx.compose.ui.window.MetalRedrawer.$<init>$lambda$1$FUNCTION_REFERENCE$5.invoke#internal + 72
	20  iosApp                              0x0000000103299de0 kfun:androidx.compose.ui.window.MetalRedrawer.$<init>$lambda$1$FUNCTION_REFERENCE$5.$<bridge-DNN>invoke(){}#internal + 72
	21  iosApp                              0x0000000102154704 kfun:kotlin.Function0#invoke(){}1:0-trampoline + 100
	22  iosApp                              0x000000010329ab90 kfun:androidx.compose.ui.window.DisplayLinkProxy.handleDisplayLinkTick#internal + 156
	23  iosApp                              0x000000010329ac50 kfun:androidx.compose.ui.window.DisplayLinkProxy.$imp:handleDisplayLinkTick#internal + 156
	24  QuartzCore                          0x000000018a02366c _ZN2CA7Display15DisplayLinkItem9dispatch_ERNS_8SignPost8IntervalILNS2_11CAEventCodeE835322056EEE + 44
	25  QuartzCore                          0x000000018a01fe44 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 808
	26  QuartzCore                          0x000000018a120c98 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 336
	27  CoreFoundation                      0x00000001803d8a20 __CFMachPortPerform + 172
	28  CoreFoundation                      0x000000018040f588 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
	29  CoreFoundation                      0x000000018040eb58 __CFRunLoopDoSource1 + 496
	30  CoreFoundation                      0x0000000180409168 __CFRunLoopRun + 2176
	31  CoreFoundation                      0x00000001804084d4 CFRunLoopRunSpecific + 572
	32  GraphicsServices                    0x000000018ef2aae4 GSEventRunModal + 160
	33  UIKitCore                           0x00000001853d0a28 -[UIApplication _run] + 868
	34  UIKitCore                           0x00000001853d46b0 UIApplicationMain + 124
	35  SwiftUI                             0x00000001ccf100e4 OUTLINED_FUNCTION_65 + 492
	36  SwiftUI                             0x00000001ccf0ff8c OUTLINED_FUNCTION_65 + 148
	37  SwiftUI                             0x00000001ccbcd6d8 OUTLINED_FUNCTION_0 + 92
	38  iosApp                              0x00000001001d0770 $s6iosApp05NexTvB0V5$mainyyFZ + 40
	39  iosApp                              0x00000001001d081c main + 12
	40  dyld                                0x0000000109171544 start_sim + 20
	41  ???                                 0x000000010935a0e0 0x0 + 4449476832
	42  ???                                 0xb751800000000000 0x0 + 13209479919542730752
)
libc++abi: terminating due to uncaught exception of type NSException

@Stuart-campbell
Copy link
Author

I am using 1.7.3 as well. Work around is not show in a modal. So it's a UX work around not a technical one. Thanks

@JayShortway
Copy link
Member

Thanks for sharing the stack trace! I can also reproduce this when trying to show the paywall in an AlertDialog (generally not recommended, just an experiment). This makes me think it has to do with trying to present the paywall in a new window. I'm still leaning towards a UIKit interop bug.

An alternative approach is to display the paywall in the sheetContent of a ModalBottomSheetLayout. This doesn't use a separate window for the bottom sheet. I tried it and it works on my end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants