Reputation: 4084
I recently had a problem regarding not being able to register touches events (touchesMoved
, etc) from within a UIScrollView
. After talking with lots of people and reading tons of posts, it turns out UIScrollView
does't accept touches itself, and instead the touches need to be passed to a UIScrollView
subclass.
I am very new to objective-c, and am having a terrible time wrapping my head around how subclasses are defined (in separate .h/.m files or somehow in @interface or something), as well as how iOS deals with responder chains.
Please let me describe my exact situation, and anyone willing to explain what I need to do in noob-speak will be really appreciated.
I have a single page in my app, and I changed it's default UIView
to UIScrollView
, so if I inspect it in InterfaceBuidler
all I see is my SampleViewController
and UIScrollView
. I linked my UIScrollView
to the @Interface
of SampleViewControler.h
like this:
#import <UIKit/UIKit.h>
@interface SampleViewController : UIViewController
{
}
@property (strong, nonatomic) IBOutlet UIScrollView *mainScroller;
@end
And I referenced my UIScrollView
in SampleViewController.m
like this:
#import "SampleViewController.h"
@interface SampleViewController ()
@end
@implementation SampleViewController
@synthesize mainScroller = _mainScroller;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Movement!");
}
-(void)viewWillAppear:(BOOL)animated
{
[_mainScroller setContentOffset:CGPointMake(0,0) animated:YES];
}
If I change the class of UIScrollView
to UIView
, the touches are detected and I fire off a few NSLog
messages. However, once UIView
is set back to UIScrollView
, touches are ignored.
From what I understand I need to setup a subclass of UIScrollView
with the code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Movement!");
}
...and then change my SampleViewController.m to have the code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self.nextResponder nextResponder] touchesMoved:touches withEvent:event];
}
However, I really don't understand 1) how to setup such a subclass, and 2) why this would work, since I don't see why [[self.nextResponder nextResponder] touchesMoved:touches withEvent:event];
would ever be called in the first place from within SampleViewController.m
, since my similar NSLog(@"Movement!");
statement is never executed.
I have tried every tutorial I could find, and am turning toward to the expertise of SE! Thanks.
Upvotes: 3
Views: 2236
Reputation: 11682
I posted an answer to a similar question a few days ago that might help you as well. See this question and my answer.
It looks like you're close to getting it working, but you've gotten a bit confused about where to put the touchesMoved
methods.
In your subclass of UIScrollView
, you should have:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self.nextResponder nextResponder] touchesMoved:touches withEvent:event];
}
And in your SampleViewController.m
file:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Movement!");
}
(You have these two around the other way in your question.)
Upvotes: 0
Reputation: 13549
You're thinking about this wrong. If you want to know when a scrollView is moving, there's no need to subclass it. iOS has set up all the methods you need inside of the UIScrollViewDelegate
. IF however you want to say, pick up touchEvents for items based inside the scrollView, then that is perfectly okay. You need to then just subclass the items inside the scrollView and pick up the touchEvents inside the respective classes though. But for just standard scrollView methods you should set it up as so:
.H
#import <UIKit/UIKit.h>
@interface SampleViewController : UIViewController<UIScrollViewDelegate>
{
}
@property (strong, nonatomic) IBOutlet UIScrollView *mainScroller;
@end
.M
#import "SampleViewController.h"
@interface SampleViewController ()
@end
@implementation SampleViewController
@synthesize mainScroller = _mainScroller;
-(void)viewDidLoad
{
self.mainScroller.delegate=self;//Adopt the delegate for the scrollView..this is the important line
}
Then just implement the UIScrollViewDelegateMethods to grab movement etc. Undefined behavior will occur when trying to pick up touchEvents inside a scrollView/tableView, since the scrollView itself already implements those touchEvents behind the scenes
Look at all the methods on the Developer site and implement them in your .M file. Since you've adopted the delegate in viewDidLoad, these will be your scrollView call backs. I've listed a few of them before but go ahead and look on the UIScrollViewDelegate Protocol site
– scrollViewDidScroll:
– scrollViewWillBeginDragging:
– scrollViewWillEndDragging:withVelocity:targetContentOffset:
– scrollViewDidEndDragging:willDecelerate:
– scrollViewShouldScrollToTop:
– scrollViewDidScrollToTop:
– scrollViewWillBeginDecelerating:
– scrollViewDidEndDecelerating:
Upvotes: 1