warning: class 'CardController' does not implement the 'UIGestureRecognizerDelegate' protocol - iphone

In my app i am trying to detect swipe gesture to navigate to the next page ...
Please find my below code below
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRightAction:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
swipeRight.delegate = self;
[cardsGridView addGestureRecognizer:swipeRight];
when i run my application, i get the below warning...
warning: class 'MyGesture' does not implement the 'UIGestureRecognizerDelegate' protocol
Kindly help me up that what i am missing here.
UPDATE1 : can anybody pls show me a working code to detect the swipe....

The UIGestureRecognizerDelegate protocol only defines optional methods. There are now two ways to get rid of the warning:
Do not set the delegate at all if you do not need any of those optional delegate methods. Your swipeRightAction method call will work anyway as you specify the target and the selector in the initializer.
If you need to set the delegate, indicate in the header file of your delegate class that the class implements the protocol by specifying it in angle brackets after your superclass name:
#interface YourClass : UIViewController <UIGestureRecognizerDelegate> {
...
}
Edit: Thanks, I forgot to escape the angle brackets.

Related

Apply PanGesture to uiview in another class with action

I have a ViewController iDragHomeViewController
and another
NSObject class iDrag
"iDragHomeViewController.m"
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *dragView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];
[dragView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:dragView];
iDrag *drag = [[iDrag alloc]init];
[drag makeDraggableView:dragView];
}
"iDrag.m"
-(void)makeDraggableView: (UIView *)dragView {
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(cellPan:)];
[dragView addGestureRecognizer:panRecognizer];
}
- (void)cellPan:(UIPanGestureRecognizer *)iRecognizer {
UIView *viewToDrag = [[UIView alloc]init];
viewToDrag = iRecognizer.view;
CGPoint translation = [iRecognizer translationInView:[viewToDrag superview]];
viewToDrag.center = CGPointMake(iRecognizer.view.center.x + translation.x,
iRecognizer.view.center.y + translation.y);
[iRecognizer setTranslation:CGPointMake(0, 0) inView:[viewToDrag superview]];
}
Now what I am trying here is to make this "dragView"(belongs to iDragHomeViewController) draggable in iDrag class by applying it PanGesture.
But the code is crashing.
I know some people will suggest me to use NSNotification to handle Pan action in another class but I dont want to write a single line in iDragHomeViewController and handle everything in iDrag Class only.
Is it Possible ??
Please Help.
To be sure I need to know the error output but a guess...
From UIGestureRecognizer doc:
- (id)initWithTarget:(id)target action:(SEL)action
target parameter:
An object that is the recipient of action messages sent by the receiver when it recognizes a gesture. nil is not a valid value.
Thats the reason why your app crashes. The drag object is already released while the recognizer tries to call the cellPan: method.
You initialize the iDrag object in viewDidLoad and is not retained. (It is not a member variable and not used anywhere else....). End of the viewDidLoad the iDrag object is released by ARC.
I would not make any other object responsible for handling pan gestures, unless I had a good reason for that. And would make the view controller responsible for creating gesture recognizer and handling the events.
I assume you have really good reason for that, like the handling is used by multiple views, etc... If it is the case then a better approach would be making iDrag object singleton(shared instance).
Got the answer
Just need to declare iDrag object as a property
#property(nonatomic,strong) iDrag *drag;

Way to ignore "UIViewController may not respond to [method]" warning

Is there a way to make the compiler ignore this specific warning?
Here's what I do:
UIViewController *firstViewController = AppDelegate.instance.viewController;
//open the view of the clicked subItem
if ([firstViewController respondsToSelector:#selector(openView:inView:)]) {
[firstViewController openView:subItem.itemText.text inView:activeScreen]; //warning on this line
}
I know one way that works is to change UIViewController to ViewController (Name of it's class). But this fix won't work in the future, so I'm just looking for a way to ignore this warning.
It won't work in the future because, I'll be doing something like this:
//.m
UIViewController *firstViewController;
//.h
if (someCondition) {
firstViewController = AppDelegate.instance.viewController;
}
else{
firstViewController = AppDelegate.instance.otherViewController;
}
if ([firstViewController respondsToSelector:#selector(openView:inView:)]) {
[firstViewController openView:subItem.itemText.text inView:activeScreen]; //warning on this line
}
You should cast the object to the correct type where appropriate. Note that you can 'cast' to a protocol if you like. This gives you the safety of knowing that required methods are implemented without having to know the concrete type.
If you want to just have the compiler not complain, it's possible by calling performSelector:. But then you won't get compile-time checking.
[object performSelector:#selector(doSomething)];
See discussion: Using -performSelector: vs. just calling the method
If you want to pass exactly one object to your selector, it's possible by using the variant performSelector:withObject:.
If you want to pass multiple objects, you'll have to wrap them up in a container object, as described at iOS - How to implement a performSelector with multiple arguments and with afterDelay?.
In this case, you can just issue an explicit type conversion (cast):
UIViewController *firstViewController;
// ...
[(FirstViewController *)firstViewController openView:subItem.itemText.text inView:activeScreen];
Make sure to import the FirstViewController.h, so that method is known to the compiler. Tweak your code a bit:
UIViewController *vc = AppDelegate.instance.viewController;
//open the view of the clicked subItem
if ([vc respondsToSelector:#selector(openView:inView:)]) {
FirstViewController *firstViewController = (FirstViewController *) vc;
[firstViewController openView:subItem.itemText.text inView:activeScreen];
}
That should do the trick.

How to Use UIGesterRecognizer within Subclass

I have a subclass:
CustomView : UIScrollView.
Inside of this subclass I have some methods that, say, populate my custom view with some UI elements. I want to add UIGesterRecognizer functionality to these elements but I do not know how to handle setting the delegate and adding selectors:
#implementation CustomView
-populateMe{
UIImageView *iv = [...];
UIGesterRecognizer r = [UIGesterRecognizer alloc]
initWithTarget:self
action:#selector(handleMySwipe:);
//<==where to declare handler
r.delegate = self; //<==COMPILER ERROR self
[iv.addGestureRecognizer r];
}
So my problem is where I commented above: self is not a valid delegate (I tried self.superclass) and where do I need to declare a handler for action, i.e. handleMySwipe.
Please explain so I understand.
CustomView is potentially a delegate, if you implement the UIGestureRecognizerDelegate protocol for it. That is, implement a few methods within your CustomView class that the protocol requires you to.
Once you've done that, you should be able to set the target parameter to self without any errors. Since your target is now self, you need to implement the selector/method handleMySwipe: within your CustomView class because that is where it will look for it (the target).
- (void) handleSwipe:(UIGestureRecognizer *)gr {
}

Semantic issue when I load GameCenter Leaderboard

I have a warning message when I load Game Center Leaderboards with:
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != nil) {
leaderboardController.leaderboardDelegate = self;
[self presentModalViewController:leaderboardController animated:YES];
}
Warning massage appears in third line, and It says:
warning: Semantic Issue: Assigning to
'id' from incompatible type
'ViewMenuController *'
I understand the message but I don't know how solve it.
The code works fine, but I would like remove the warning or find if there is a better way to load leaderboards.
Thanks in advance.
Solution:
I have done two modifications in ViewMenuController.h:
Add this import:
#import <GameKit/GameKit.h>
and modify this line adding :
#interface ViewMenuController : UIViewController <GKLeaderboardViewControllerDelegate> {
Thanks everybody for your help!
Best guess is when you are setting the leaderboardDelegate to self, it is expecting a id<GKLeaderboardViewControllerDelegate>, but your ViewMenuController does not define itself as conforming to the GKLeaderboardViewControllerDelegate protocol.
Make sure you set this in the interface of ViewMenuController.

MKAnnotation protocol

Im currrently going through a geolocation tutorial which adopts the MKAnnotation Protocol into a class.
The tutorial suggests to create the following methods in the Theannotation.h class
+ (id)annotationWithCoordinate:(CLLocationCoordinate2D)coord;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord;
and in the implementation
+ (id)annotationWithCoordinate:(CLLocationCoordinate2D)coord {
return [[[[self class] alloc] initWithCoordinate:coord] autorelease];
}
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord {
if ( self = [super init] ) {
self.coordinate = coord;
}
return self;
}
The second method is then called in a viewcontroller
Theannotation *annotation = [[SimpleAnnotation alloc] initWithCoordinate:Coords];
I understand the second method completely however Im puzzled to the inclusion of the first. The class method isn't called at any other place in the example tutorial and im struggling to understand why you would use a class method in this case.
You can omit this class method but in some cases it is useful because it provides you a mechanism to create 'temporary' annotation that will be autoreleased. Of course you can do it manually, but class method is a way of convenience in that case.
please go through this blog here
or you can download the code-
link
and see the code, you will know that which things are mandatory and which will not.