Skip to content

Commit

Permalink
Paywalls: fix template 4 layout bug on iOS 16 (#3381)
Browse files Browse the repository at this point in the history
This only reproduces on iOS 16 and using the new `displayCloseButton:
true` (because it embeds `PaywallView` in a `NavigationView`).


![simulator_screenshot_EB70C623-426F-44C5-92BA-0BDA0D3F5AFE](https://github.com/RevenueCat/purchases-ios/assets/685609/737680e1-4b95-41f3-9a09-c6e6cb7bd36e)

The problem was that the template used `ViewDimentionPreferenceKey` in
several parts of the hierarchy and `SwiftUI` mixes both.
I work around it by separating `onWidthChange` and `onHeightChange`.
  • Loading branch information
NachoSoto committed Nov 3, 2023
1 parent b5a35f6 commit 2e37c30
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 18 deletions.
2 changes: 1 addition & 1 deletion RevenueCatUI/Modifiers/FooterHidingModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private struct FooterHidingModifier: ViewModifier {

case .condensedFooter:
content
.onSizeChange(.vertical) { if $0 > 0 { self.height = $0 } }
.onHeightChange { if $0 > 0 { self.height = $0 } }
.opacity(self.hide ? 0 : 1)
.offset(
y: self.hide
Expand Down
57 changes: 43 additions & 14 deletions RevenueCatUI/Modifiers/ViewExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,24 +192,40 @@ extension View {
.onPreferenceChange(ViewSizePreferenceKey.self, perform: closure)
}

/// Invokes the given closure with the dimension specified by `axis` changes whenever it changes.
func onSizeChange(
_ axis: Axis,
/// Invokes the given closure with the view width whenever it changes.
@ViewBuilder
func onWidthChange(
_ closure: @escaping (CGFloat) -> Void
) -> some View {
self
.overlay(
GeometryReader { geometry in
Color.clear
.preference(
key: ViewDimensionPreferenceKey.self,
value: axis == .horizontal
? geometry.size.width
: geometry.size.height
key: ViewWidthPreferenceKey.self,
value: geometry.size.width
)
}
)
.onPreferenceChange(ViewDimensionPreferenceKey.self, perform: closure)
.onPreferenceChange(ViewWidthPreferenceKey.self, perform: closure)
}

/// Invokes the given closure with the view height whenever it changes.
@ViewBuilder
func onHeightChange(
_ closure: @escaping (CGFloat) -> Void
) -> some View {
self
.overlay(
GeometryReader { geometry in
Color.clear
.preference(
key: ViewHeightPreferenceKey.self,
value: geometry.size.height
)
}
)
.onPreferenceChange(ViewHeightPreferenceKey.self, perform: closure)
}

}
Expand Down Expand Up @@ -272,14 +288,13 @@ private struct RoundedCorner: Shape {

// MARK: - Preference Keys

/// `PreferenceKey` for keeping track of a view dimension.
private struct ViewDimensionPreferenceKey: PreferenceKey {

typealias Value = CGFloat
@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.2, *)
private protocol ViewDimensionPreferenceKey: PreferenceKey where Value == CGFloat {}

static var defaultValue: Value = 10
@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.2, *)
extension ViewDimensionPreferenceKey {

static func reduce(value: inout Value, nextValue: () -> Value) {
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
let newValue = max(value, nextValue())
if newValue != value {
value = newValue
Expand All @@ -288,6 +303,20 @@ private struct ViewDimensionPreferenceKey: PreferenceKey {

}

/// `PreferenceKey` for keeping track of a view width.
private struct ViewWidthPreferenceKey: ViewDimensionPreferenceKey {

static var defaultValue: Value = 10

}

/// `PreferenceKey` for keeping track of a view height.
private struct ViewHeightPreferenceKey: ViewDimensionPreferenceKey {

static var defaultValue: Value = 10

}

/// `PreferenceKey` for keeping track of view size.
private struct ViewSizePreferenceKey: PreferenceKey {

Expand Down
6 changes: 3 additions & 3 deletions RevenueCatUI/Templates/Template4View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ struct Template4View: TemplateViewType {
.scrollableIfNecessary(.horizontal)
.frame(height: self.packageContentHeight)
.frame(maxWidth: .infinity)
.onSizeChange(.horizontal) {
.onWidthChange {
self.containerWidth = $0
}
}
Expand Down Expand Up @@ -179,7 +179,7 @@ struct Template4View: TemplateViewType {
selected: false,
packageWidth: self.packageWidth,
desiredHeight: nil)
.onSizeChange(.vertical) {
.onHeightChange {
if $0 > self.packageContentHeight ?? 0 {
self.packageContentHeight = $0
}
Expand Down Expand Up @@ -374,7 +374,7 @@ private struct PackageButton: View {
.lineLimit(1)
.minimumScaleFactor(0.5)
.padding(.horizontal, 2)
.onSizeChange(.vertical) {
.onHeightChange {
self.discountLabelHeight = $0
}
.offset(
Expand Down

0 comments on commit 2e37c30

Please sign in to comment.