I recently had the need to delay a call, but only after a very slight delay.
I had a UITableView that when scrolled a certain way would resize itself, and I’d want to have it scroll to it’s top programmatically at that point. But I didn’t want the momentum of a user’s manipulation of the contentOffset to be so great as to make the scrolling to it’s top look out of place and abrupt.
I needed to gate the momentum generated by a user, so I’d want to delay the deactivation of scrollingEnabled. Not immediately, but just by a tiny bit.
I needed a way to do this kind of bizarre thing and found a wonderful bit of code online that does exactly what I want. If I could adjust the speed of setContentOffset:animated I could have done that (perhaps).
When I implemented it, it looked bizarre. It’s a method inside of another method. The code around it isn’t exactly tight or anything, but the delay call is über cool.
func scrollViewDidScroll(scrollView: UIScrollView) {
let py = scrollView.contentOffset.y
if topCollapsed == false && py > 0 {
topCollapsed = true
var placeX:CGFloat = 25.0
for subview in pvs {
subview.changeToList(false)
UIView.animateWithDuration(0.2, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {
subview.center = CGPoint(x:placeX, y:25)
}, completion: {
(finished: Bool) -> Void in
})
placeX = placeX + 53
}
delay(0.06){
self.myTable.scrollEnabled = false
}
compressTop(true)
...
Here is that magical bit of code that delays whatever you’d like by a Double.
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
That’s pretty slick, right?