Is there any notification sent when UIScrollView changes its scroll state? I would like to listen to that notification rather than using delegate methods.
If you don't want to use delegate methods you can observe contentOffset value changes using KVO (key-value-observing)
You can subclass UIScrollView, overload touchesMoved:withEvent:, and send this notification every time your scroll view will scroll.
As the scrolls need to be lightweight events I would not recommend using notifications for every scroll as it will impact your performance much greater than using a delegate method.
These are the delegates that handle scrolling for UIScrollView.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
Is there any specific reason you dont prefer delegates & want notifications? So you can use scrollViewDidScroll for any changes in scroll state.
Related
i need to add NSViewBoundsDidChangeNotification to my iphone application to check if user has scrolled the tableview,however to add this i think i need to import the nsview class.from where should i add this class to my project.and i need to confirm is this the best way to check if my tableview is scrolled by user?
NSView does not exist on the iPhone, as it uses Cocoa-Touch and not Cocoa.
If you want to get notifications about a UITableView's scroll events, just implement the UIScrollView delegate. It's documented here.
The delegate method you'll want to use is this one:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
}
There are other handy methods in there though, like:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{
}
NSView has nothing to do with IOS development.
UITableView is a subclass of UIScrollView, and UITableViewDelegate conforms to UIScrollViewDelegate. This means that the delegate you set on your UITableView will get all the calls defined for UIScrollViewDelegate, including scrollViewDidScroll:.
I'm coding an app that works much like Apple's Weather.app: There's a UIPageControl at the bottom and a UIScrollView in the middle of the screen.
In my code, I implemented the - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView method to figure out when the user did move to a new page. If they move to a new page, I load the adjacent pages' data, as to make further page-switching faster. (In one of Apple's examples, the - (void)scrollViewDidScroll:(UIScrollView *)sender is used, but that causes my app to shortly hang when loading a new page, so it's not suitable.)
That code works very well.
I'm using scrollRectToVisible:: to programmatically scroll inside the scrollview when the user clicks the UIPageControl. The problem is that the scrollRectToVisible: doesn't post a notification to the UIScrollViewDelegate when it's done scrolling - so the code responsible for loading adjacent pages never get's called when using the UIPageControl.
Is there any way to make the UIScrollView notify its delegate when it gets called by the scrollRectToVisible: method? Or will I have to use threads in order to prevent my app from freezing?
Thanks!
-- Ry
How about -scrollViewDidEndScrollingAnimation:?
If it doesn't work, try to listen to the UITextSelectionDidScroll notification. (Of course, it's undocumented.)
Alternatively, an SDK-safe method is measure the time taken for the animation and send a delayed notification at the call site of -scrollRectToVisible:.
You could add this delegate method instead:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
The scroll view calls this method at the end of its implementations of the UIScrollView and setContentOffset:animated: and scrollRectToVisible:animated: methods, but only if animations are requested.
I have this subclass of UIScrollView:
#interface MyScrollView : UIScrollView <UIScrollViewDelegate>
And I have those delegate methods
- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale(float)aScale{
NSLog(#"zoomed");
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView{
NSLog(#"willzoom");
}
When I zoom in MyScrollView viewForZoomingInScrollView is called but scrollViewDidEndZooming never gets called.
Any idea why??
Ok, completely revised answer based on your comment below. This may just be another typo, but your method signature is missing the final parameter.
Instead of:
- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale{
NSLog(#"zoomed");
}
You should have:
- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)aScale{
NSLog(#"zoomed");
}
Sorry to bump the thread, but it is a very important question. You don't say whether you are implementing a separate pinch gesture recogniser or using the built in zooming of UIScrollView. From my own researches I have found that if you just use UIScrollView to zoom it calls viewForZoomingInScrollView to get the view you want to zoom. Then it calls scrollViewWillBeginZooming, then as it zooms it calls scrollViewDidZoom repeatedly and when it finished it calls scrollViewDidEndZooming. All as you would expect.
However, if you implement your own pinch gesture recognizer to make the zoom smoother or for any other reason, it only calls viewForZoomingInScrollView at the start and scrollViewDidZoom repeatedly. I think this is because you have overridden the built in zoom functionality that calls the other methods.
If you need more control put it into an action method connected to the pinch gesture recogniser.
I'm trying to figure out how to calculate where the scrollview will stop when a user does a swipe gesture and the scrollview goes into deceleration. I'm trying to use the delegate functions, but I can't accurately figure it out. Please help!
- (void) scrollViewDidScroll:(UIScrollView *)scrollView;
- (void) scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
This thread is a bit old, but still comes up top in a search for this problem.
The UIScrollViewDelegate protocol contains the following method that tells your code where the scroll view is expected to stop...
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
The targetContentOffset parameter is an inout so if you set it to a different value, the scrollview will actually come to a stop at the offset you specify.
Unfortunately UIScrollView doesn't work this way-- there's no way to ask it up front where the deceleration ends.
Sounds complicated. The user may start scroll again while it is decelerating, stop it suddenly or what not. Maybe you can get by with just doing DidEndDecelerating, i.e just detecting the position when the scrolling is over?
It should be simple math. The contentOffset property of the scrollview is updated each time scrollViewDidScroll is called. You only need to save the vector between two positions and the time to get at least a descent end-position of the deceleration.
Note that the user can stop the deceleration any time by tapping on the scrollview as Jaanus pointed out.
There is a variable for the current acceleration that is kept in the UIScrollView implementation but using that as a solution is impossible because you can't compile the code for a device.
In the iPhone 3.0 SDK, how can I be informed when a zoomToRect:animated: animation completes?
Sometimes the scrollview doesn't zoom at all (if it's already at the proper zoom level), and there doesn't seem to be a way to detect that.
On your delegate, you can listen for - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
see UIScrollView and UIScrollViewDelegate
The easiest way would probably to put in a check before starting the animation. If the zoom level is already correct, call [self performSelectorOnMainThread:#selector(myMethod) withObject:id waitUntilDone:NO].
You won't be able to use the same method as scrollViewDidEndZooming, because you can only pass one argument, but it will trigger an asynchronous call on the main thread