Всплывающее окно не отображается на iPad, если исходный вид большой

#ios #swift

Вопрос:

У меня есть а UIScrollView , и внутри есть UIView А. Я хочу показать UIColorPickerViewController , когда пользователь долго нажимает на это представление. Вид прокрутки можно увеличивать/уменьшать. Проблема в том, что когда я увеличиваю изображение прокрутки и вид внутри почти равен или превышает границы устройства, всплывающее окно не отображается при длительном нажатии. Это происходит для любого UIViewController , показанного в качестве всплывающего окна. Проблема возникает только внутри iPads и отлично работает внутри iPhones .

У кого-нибудь есть идеи, почему это происходит?

Работает, как и ожидалось, в iPhone

введите описание изображения здесь

В iPad, если я просто увеличу немного больше второй сценарий(второе изображение), всплывающее окно не будет отображаться при длительном нажатии. введите описание изображения здесь

Это пример кода

 class ScrollViewController: UIViewController {
    let scrollView = UIScrollView()
    let colorView = UIView()
    
    override func loadView() {
        super.loadView()
        
        let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(showColorPicker(_:)))
        colorView.frame = CGRect(x: 200, y: 200, width: 400, height: 400)
        colorView.backgroundColor = .systemBlue
        colorView.addGestureRecognizer(longPressRecognizer)
        colorView.isUserInteractionEnabled = true
        
        scrollView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
        scrollView.contentSize = CGSize(width: self.view.frame.width, height: 4000)
        scrollView.minimumZoomScale = 0.1
        scrollView.maximumZoomScale = 10
        scrollView.delegate = self
        scrollView.backgroundColor = .white
        
        scrollView.addSubview(colorView)
        
        self.view.addSubview(scrollView)
    }
    
    @objc func showColorPicker(_ sender: UITapGestureRecognizer) {
        let colorPicker = UIColorPickerViewController()
        colorPicker.modalPresentationStyle = .popover
        colorPicker.popoverPresentationController?.canOverlapSourceViewRect = true
        colorPicker.popoverPresentationController?.sourceView = colorView
        colorPicker.popoverPresentationController?.sourceRect = self.colorView.bounds
        colorPicker.popoverPresentationController?.permittedArrowDirections = .any
        
        self.present(colorPicker, animated: true, completion: nil)
    }
}

extension ScrollViewController: UIScrollViewDelegate {
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return scrollView.subviews.first
    }
}

 

Ответ №1:

В качестве обходного пути для этой проблемы мы можем указать a sourceRect , которое находится внутри границ устройства , когда sourceView оно больше границ устройства.

 @objc func showColorPicker(_ sender: UITapGestureRecognizer) {
    let colorPicker = UIColorPickerViewController()
    colorPicker.modalPresentationStyle = .popover
    colorPicker.popoverPresentationController?.canOverlapSourceViewRect = true
    colorPicker.popoverPresentationController?.sourceView = self.colorView
    colorPicker.popoverPresentationController?.permittedArrowDirections = .any
    
    let point = sender.location(in: self.colorView)
    //set a sourceRect which is guranteed to be inside the device bounds when the colorView exceeds the devie bounds
    if (scrollView.bounds.size.width - self.colorView.frame.width) < 0 || (scrollView.bounds.size.height - self.colorView.frame.height) < 0 {
        colorPicker.popoverPresentationController?.sourceRect = CGRect(origin: point, size: CGSize(width: 1, height: 1))
    } else {
        colorPicker.popoverPresentationController?.sourceRect = self.colorView.bounds
    }
    
    self.present(colorPicker, animated: true, completion: nil)
}
 

введите описание изображения здесь