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?