UIScrollView рекурсия
В UIScrollViewDelegate
scrollViewDidScroll(UIScrollView)
функция, если вы измените кадр делегата UIScrollView
, затем scrollViewDidScroll(UIScrollView)
снова вызывается. Типичный пример этого - когда у вас есть заголовок, который сжимается при прокрутке пользователя вверх и расширяется при прокрутке пользователя вниз.
Помимо реализации, в которой вы сбрасываете и сбрасываете свойство делегата scrollView, как показано ниже, есть ли способы предотвратить рекурсию? Объект UIScrollView имеет isTracking
а также isDragging
свойства, которые перекрываются, а также остаются верными в следующем примере.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let d = scrollView.delegate // Prevent recursion by setting the
scrollView.delegate = nil
// Do stuff
if someCondition == true {
scrollView.contentOffset = somePoint
scrollView.frame = someRect
}
scrollView.delegate = d // Restore the scrollView's delegate
}
ПРИМЕЧАНИЕ: мне не нужен учебник для создания складного заголовка, и мне не нужен простой, если проверка. Я только конкретно спрашиваю, какие варианты доступны для прерывания прокрутки событий в зависимости от их происхождения. Например, вы можете поставить это в начале scrollViewDidScroll
:
if(!scrollView.isTracking && !scrollView.isDragging) {
// Break out if we got here through anything but a touch event
return
}
1 ответ
Я просто попробовал, и настройка .contentOffset
не вызывает рекурсии.
При перетаскивании содержимого делегат получает непрерывный scrollViewDidScroll
сообщения... когда вы звоните:
scrollView.contentOffset = CGPoint(x: 0, y: 0)
вы все еще перетаскиваете, и содержимое продолжает сбрасываться до 0,0.
Измените свою функцию на это:
var i = 0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
i += 1
print("did scroll", i)
scrollView.contentOffset = CGPoint.zero
}
и вы увидите, что он перестанет считать, когда вы прекратите перетаскивать, поэтому он не рекурсивный.
Возможно, вы действительно хотите использовать scrollViewDidEndDragging
или же scrollViewDidEndDecelerating
?
Редактировать:
Возможно, это будет работать лучше для вас. Имейте в виду, пока вы продолжаете перетаскивать в представлении прокрутки, scrollViewDidScroll()
будет продолжать называться.
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
print("did end dragging", scrollView.contentOffset)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("did scroll", scrollView.contentOffset)
scrollView.setContentOffset(CGPoint.zero, animated: false)
}
Если вы посмотрите на вывод консоли, вы никогда не увидите больше 2 print() после того, как "перестанете перетаскивать".