Search code examples
iosuikituistackview3dtouchpeek-pop

UIStackView Peek and Pop overlay glitch


I'm trying to implement Peek and Pop with the contents of a UIStackView. The problem is that the overlay (the part that isn't blurred) during the shallow press doesn't contain the right contents. It's in the right place, since it's right below my finger, but the contents seem to be taken from elsewhere in the view:example

Steps to reproduce:

  1. Open an empty iOS project using storyboards
  2. Add a UIStackView to the view controller's view
  3. Add nearest neighbors constraints from all four sides of the stack view equal to 0
  4. Replace the contents of ViewController.swift with the following code:

    import UIKit
    
    class ViewController: UIViewController {
        @IBOutlet var stackView: UIStackView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            registerForPreviewing(with: self, sourceView: stackView)
    
            let loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sed feugiat ligula. Sed in rutrum lacus, vel auctor felis. Vivamus molestie felis nisi. Mauris euismod eros vitae libero commodo porttitor. Nam posuere, dui vitae aliquam mollis, quam mauris tempus turpis."
    
            let label = UILabel()
            label.numberOfLines = 0
            label.text = repeatElement(loremIpsum, count: 4).joined(separator: "\n\n")
            stackView.addArrangedSubview(label)
        }
    }
    
    extension ViewController: UIViewControllerPreviewingDelegate {
        func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
            previewingContext.sourceRect = CGRect(x: location.x - 50, y: location.y - 50, width: 100, height: 100)
            return storyboard?.instantiateInitialViewController()
        }
    
        func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
            present(viewControllerToCommit, animated: true)
        }
    }
    
  5. Run the app on your (physical) device and force touch anywhere

Am I doing something wrong, or is this a bug in UIKit?

Edit: This is how I expected it to behave: example


Solution

  • Replacing

    registerForPreviewing(with: self, sourceView: stackView)
    

    by

    registerForPreviewing(with: self, sourceView: view)
    

    solved the problem. I still suspect that it's a bug, but at least this is a workaround.