Swift: Pull down To disclude ' UITableViewController`

Chcę pociągnąć w dół, aby odrzucić UITableViewController więc użyłem metody scrollViewDidScroll, ale nie działa!

    class CommentViewController: PFQueryTableViewController {

        private let tableHeaderHeight: CGFloat = 350.0



extension CommentViewController
{
    override func scrollViewDidScroll(scrollView: UIScrollView)
    {



            // Pull down to dismiss TVC 
            let offsetY = scrollView.contentOffset.y
            let adjustment: CGFloat = 130.0

            // for later use
            if (-offsetY) > (tableHeaderHeight+adjustment) {
                self.dismissViewControllerAnimated(true, completion: nil)
                }
 }
    }
Author: marrioa, 2015-11-19

4 answers

Musisz zaimplementować dodatkowy system rozpoznawania gestów przesuwania, który będzie rozpoznawał jednocześnie z funkcją rozpoznawania gestów przesuwania scrollView. Następnie możesz określić, czy użytkownik jest przesuwany palcem, gdy widok tabeli jest już przewinięty do góry. np.

var isTrackingPanLocation = false
var panGestureRecognizer: UIPanGestureRecognizer!

public override func viewDidLoad() {
    super.viewDidLoad()
    tableView.bounces = false
    panGestureRecognizer = UIPanGestureRecognizer(target: self, 
                                                  action: #selector(panRecognized(gestureRecognizer:)))
    panGestureRecognizer.delegate = self
    tableView.addGestureRecognizer(panGestureRecognizer)
}

public func panRecognized(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == .began && tableView.contentOffset.y == 0 {
        recognizer.setTranslation(CGPoint.zero, inView : tableView)

        isTrackingPanLocation = true
    } else if recognizer.state != .ended && 
              recognizer.state != .cancelled && 
              recognizer.state != .failed && 
              isTrackingPanLocation {
        let panOffset = recognizer.translationInView(tableView)

        // determine offset of the pan from the start here. 
        // When offset is far enough from table view top edge - 
        // dismiss your view controller. Additionally you can 
        // determine if pan goes in the wrong direction and 
        // then reset flag isTrackingPanLocation to false

        let eligiblePanOffset = panOffset.y > 200
        if eligiblePanOffset {
            recognizer.enabled = false
            recognizer.enabled = true
            dismissViewControllerAnimated(true, completion: nil)
        }

        if panOffset.y < 0 {
            isTrackingPanLocation = false
        }
    } else {
        isTrackingPanLocation = false
    }
}

public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, 
    shouldRecognizeSimultaneouslyWithGestureRecognizer 
                    otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}
 15
Author: Eugene Dudnyk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-18 02:25:08

Swift 4

var panGestureRecognizer : UIPanGestureRecognizer!

override func viewDidLoad() {
    mainTableView.bounces = true
    panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panRecognized))
    panGestureRecognizer.delegate = self
    mainTableView.addGestureRecognizer(panGestureRecognizer)
}


@objc func panRecognized(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == .began && mainTableView.contentOffset.y == 0 {

    } else if recognizer.state != .ended && recognizer.state != .cancelled && recognizer.state != .failed {
        let panOffset = recognizer.translation(in: mainTableView)
        let eligiblePanOffset = panOffset.y > 300
        if eligiblePanOffset {
            recognizer.isEnabled = false
            recognizer.isEnabled = true
            self.dismiss(animated: true, completion: nil)
        }
    }
}


func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}
 14
Author: Varun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-20 10:17:33

Dlaczego nie umieścisz print (offsetY) w scrollViewDidScroll. Podejrzewam, że (-offsetY) > (tableHeaderHeight+adjustment) nigdy nie będzie zadowolony z powodu gumowego paska spowoduje odbicie tableview, zanim będzie mógł zamknąć kontroler widoku

 2
Author: beyowulf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-20 00:39:16

Dla osób patrzących na to w 2019 roku -- bardziej nowoczesne podejście wykorzystywałoby metody UIGestureRecognizerDelegate , zamiast utrzymywania dodatkowego stanu w kontrolerze widoku. Na przykład:

private weak var panFromTop: UIPanGestureRecognizer?

override func viewDidLoad() {
    super.viewDidLoad()

    // Add pan gesture recognizer
    let panFromTop = UIPanGestureRecognizer(target: self, action: #selector(handlePanFromTop(_:)))
    panFromTop.delegate = self
    tableView.addGestureRecognizer(panFromTop)
    self.panFromTop = panFromTop
}

@objc func handlePanFromTop(_ recognizer: UIPanGestureRecognizer) {
    switch recognizer.state {
    case .began:
        // TODO: BEGIN YOUR ANIMATION HERE
    case .changed:
        // TODO: UPDATE YOUR ANIMATION HERE
    default:
        let translation = recognizer.translation(in: view)
        let velocity = recognizer.velocity(in: view)
        if ((translation.y + velocity.y) / view.bounds.height) > 0.5 {
            // TODO: FINISH YOUR ANIMATION HERE
        } else {
            // TODO: CANCEL YOUR ANIMATION HERE
        }
    }
}

Wyłączenie odbijania tylko w górnej części widoku tabeli:

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.y < 0 {
        scrollView.setContentOffset(.zero, animated: false)
    }
}

Następnie zaimplementuj metody delegowania rozpoznawania gestów:

func gestureRecognizer(
    _ gestureRecognizer: UIGestureRecognizer,
    shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
    return true
}

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    guard let recognizer = gestureRecognizer as? UIPanGestureRecognizer,
        recognizer === panFromTop else {
        // Only require special conditions for the panFromTop gesture recognizer
        return true
    }

    // Require the scroll view to be at the top,
    // and require the pan to start by dragging downward
    return (
        tableView.contentOffset.y <= 0 &&
        recognizer.velocity(in: view).y > 0
    )
}
 1
Author: Chris Chute,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-18 16:03:56