52inc / Pulley

A library to imitate the iOS 10 Maps UI.
https://cocoapods.org/pods/Pulley
MIT License
2.02k stars 265 forks source link

Unable to drag the drawer on iOS 14 #400

Closed dxt closed 3 years ago

dxt commented 3 years ago

When compiled on Xcode 12 and run on an iOS 14 device, I am unable to drag the Pulley drawer to open or close it. Swiping works fine.

Here are examples on the Demo project: Works on iOS 13 Does not work on iOS 14 This was on Pulley version 2.8.4. The same issue occurs on the iPad.

I traced through the code and found that, in iOS 14, in PulleyViewController, viewDidLayoutSubviews() is called every time after scrollViewDidScroll(_:) is called. That does not happen on iOS 13.

Also, commenting out the line setDrawerPosition(position: drawerPosition, animated: false) in viewDidLayoutSubviews() does bring back the dragging capability, but I doubt that's the right solution.

Happy to provide more information if needed.

JensDee commented 3 years ago

We had a very similar issue under iOS 12. An identical issue occurred with iOS 14 (weirdly enough it only occurred in distribution builds which was a nightmare to debug). In both cases it had to do with the internal scrollView of the PulleyViewController. It occurred when the contentHeight had decimal places. I do not recall exactly what was causing the endless layout cycles, but they occurred when the contentHeight was 1/3 px larger or smaller than the bounds of the scrollView - something like this. Anyway, long story, short suggestion: Make sure you use rounded numbers for any drawerHeight. For example, in the delegate methods collapsedDrawerHeight and partialRevealDrawerHeight add a ceil() or round().

func collapsedDrawerHeight(bottomSafeArea: CGFloat) -> CGFloat { return ceil(...) }

Hope that fixes the issue for you, too.

ulmentflam commented 3 years ago

@dxt Thanks for bring up this issue, as it seems to be related to the feedback loops I have been researching via issue #390. I will look into it as soon as I get a chance! Hopefully @JensDee's solution will be a temporary fix for you as I look into the root of this issue.

ulmentflam commented 3 years ago

@dxt So I have found the issue and am working on a fix for it now. This issue is in iOS 14 updating constant on the constraint for the temperature label is calling viewDidLayoutSubviews() when the value is updated. Therefor when scrollViewDidScroll(_:) calls the drawerChangedDistanceFromBottom(drawer:, distance:, bottomSafeArea:) delegate method in the PrimaryContentViewController.swift of the demo project, viewDidLayoutSubviews() is being called and subsequently setDrawerPosition(position: drawerPosition, animated: false) and the position of the drawer is being set to the current position and not the position of the scroll. The temporary work around is just updating the frame of the temperature label in your project instead of the constraint for now (this applies to any view you need to follow the drawer position), or if you don't need the temperature label in your project, you can remove the following block of code entirely along with the temperature label and the constraint to the temperature label. I am will let you know as soon as I have a solution that allows the use of constraints for backwards compatibility,

        guard drawer.currentDisplayMode == .drawer else {

            temperatureLabelBottomConstraint.constant = temperatureLabelBottomDistance
            return
        }

        if distance <= 268.0 + bottomSafeArea
        {
            temperatureLabelBottomConstraint.constant = distance + temperatureLabelBottomDistance
        }
        else
        {
            temperatureLabelBottomConstraint.constant = 268.0 + temperatureLabelBottomDistance
        }
ulmentflam commented 3 years ago

@dxt @JensDee A solution for this issue has been fixed and pushed via Pulley version 2.8.5! Thanks for reporting this issue!

dxt commented 3 years ago

Thank you @JensDee for the suggestion. And thank you @ulmentflam for the fix! It is much appreciated!