Multiple data objects by extension using a protocol - ios

I had the great idea to use a a protocol on the UITouch class to extend it with some methods declared in the protocol. The reason of such a construct is to provide the protocol inside a framework to other users that they can send UITouch-similar data objects (Because they can't create a native UITouch object).
The protocol (myProtocol.h) is quite easy:
// myProtocol.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol myProtocol <NSObject>
- (CGFloat) MYPREFIX_radius;
#end
Now i have a simple extension on UITouch using that protocol
// UITouch+MYPREFIX_Extension.h
#import <UIKit/UIKit.h>
#import "myProtocol.h"
#interface UITouch (MYPREFIX_Extension) <myProtocol>
#end
and
// UITouch+MYPREFIX_Extension.m
#import "UITouch+MYPREFIX_Extension.h"
#implementation UITouch (MYPREFIX_Extension)
- (CGFloat) MYPREFIX_radius {
return self.majorRadius;
}
#end
By this everything is good to me. Now I built a touchRecognizer.
// touchRecognizer.h
#import <UIKit/UIKit.h>
#interface touchRecognizer : UITouch
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
#end
In the touchRecognizer.m the problem begins. There I cast the UITouch object to a NSObject by using the protocol.And then I simply want to get access to the newly defined method MYPREFIX_radius and it should give me back the UITouch.major_radius.
// touchRecognizer.m
#import "touchRecognizer.h"
#import "UITouch+MYPREFIX_Extension.h"
#interface touchRecognizer()
#end
#implementation touchRecognizer
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for(NSObject<myProtocol> *touch in touches) {
NSLog(#"radius %f", touch.MYPREFIX_radius);
}
}
#end
But when I run the code it just gives me the Error
-[UITouch MYPREFIX_radius]: unrecognized selector sent to instance 0x1701887b0
I don't understand it. What do I miss?
Thank you for your help.

I am guessing you forget to add the implementation file (UITouch+MYPREFIX_Extension.m) to your build target

Related

Error: No Known Class method for selector 'addChild'

So, I created a new class named 'Level1Class' and I made a method named 'level1Layout'. In that method I created a SKSprite named 'level1ButtonRed' and when I set the position and try to add it by using
[self addChild: level1ButtonRed]
and it gives me the error
"No Known Class method for selector 'addChild'."
#import "Level1Class.h"
#import "GameScene.h"
#implementation Level1Class
+(void) level1Layout{
SKSpriteNode *level1ButtonRed;
level1ButtonRed = [SKSpriteNode spriteNodeWithImageNamed:#"LevelButton_Red"];
level1ButtonRed.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild: level1ButtonRed];
}
#end
#import "GameScene.h"
static NSString *levelButtonRed = #"levelButtonRed";
#implementation GameScene
SKSpriteNode *trans;
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
trans = [SKSpriteNode spriteNodeWithImageNamed:#"Transparent"];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
trans.position = location;
[self enumerateChildNodesWithName:#"levelButtonRed" usingBlock: ^(SKNode *node1, BOOL *stop1){
if( [trans intersectsNode:node1]){
[Level1Class level1Layout];
}
}];
} }
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */ }
#end
Level1Class.h
#import <SpriteKit/SpriteKit.h>
#import <Foundation/Foundation.h>
#interface Level1Class : NSObject
-(void) level1Layout;
#end
Any help??
You send that message to self inside +level1Layout. This is a class method. Therefore self points to the class object. You cannot add children to class objects. You can add children to instance objects of that class.
To solve that issue create an instance first and then add the child to that instance.

How to get a UIView object to communicate with a ViewController object

I'm working on an iPhone app in StoryBoard. It has a UIScrollView in it. Inside of this, it has a SliderView, which is a custom subclass that I wrote that derives from UIView.
Inside SliderView I'm executing this method:
// Inside SliderView.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// whenever someone touches inside of SliderView, this method fires
}
Here's my problem. In my StoryBoard, I would like to disable the bouncy vertical scrolling of the UIScrollView.
Normally, that would be easy. Assuming I had connected the UIScrollView as an IBOutlet in the app's main ViewController, I could paste this into that file:
// Inside ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.bounces = NO;
}
Unfortunately, this isn't so easy because I want this disabling to occur only when touchesBegan is fired.
So here's where I'm completely stumped: how can I get the SliderView.m file to communicate with the ViewController.m file?
Use delegate for this:
SliderView.h
// SliderView.h
#protocol SliderViewDelegate <NSObject>
#optional
- (void) isScrollViewToBounce:(BOOL)isBounce;
#end
#interface SliderView : UIView
#property (nonatomic, weak) id <SliderViewDelegate> sliderViewDelegate;
#end
SliderView.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.sliderViewDelegate isScrollViewToBounce:NO];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self.sliderViewDelegate isScrollViewToBounce:YES];
}
ViewController.m
#import "SliderView.h"
#interface ViewController () <SliderViewDelegate>
#end
viewDidLoad() method
- (void)viewDidLoad {
[super viewDidLoad];
self.sliderView setSlideViewDelegate:self];
}
Create Delegate method in your ViewController:
- (void) isScrollViewToBounce:(BOOL)isBounce {
self.scrollView.bounces = isBounce;
}
Also do not forget to remove delegation
#pragma mark Memory management methods
//---------------------------------------------------------------
- (void)dealloc {
// Release resources here.
[self.scrollView setSliderViewDelegate:nil]
}

Use of undeclared identifier 'CCJumpBy'

This is my code
#import "Gameplay.h"
#import <CCActionInterval.h>
#implementation Gameplay {
CCPhysicsNode *_physicsNode;
}
- (void)didLoadFromCCB {
// tell this scene to accept touches
self.userInteractionEnabled = TRUE;
}
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
[self jumpRunner];
}
-(void)jumpRunner {
CCNode *spaceship = [CCBReader load:#"Runner"];
id jump = [CCJumpBy actionWithDuration:1 position:ccp(100, 0)
height:50 jumps:1];
[spaceship runAction:jump];
}
#end
It's telling me
Use of undeclared identifier 'CCJumpBy'
How do I fix this to make it work? I don't know what to do.
Thanx in advance
Import cocos2d and you should resolve the error
#import "cocos2d.h"
You probably need to #import the CCJumpBy class's header file.
Also I notice that you're #importing a .m file, which generally you don't do. You probably want to change your import of CCActionInterval to be the .h file, not the .m file.
CCJumpBy is defined in CCActionInterval.h.
Change your import to
#import <CCActionInterval.h>
And you should resolve this error.

SKSpriteNode subclass and touches events

I can't understand why if I subclass a SKSpriteNode, that implements the UIResponder protocol, the methods related with touches are never been called.
For example, this is a really simple class that I'm using as test:
//INTERFACE ----------------
#import <SpriteKit/SpriteKit.h>
#interface TestClass : SKSpriteNode
#end
//IMPLEMENTATION -----------
#import "TestClass.h"
#implementation TestClass
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"oook");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{}
#end
If I attach an instance of this class to the scene, touching the object... nothing happens.
Am I forgetting something?
I've just seen that SKNode has the parameter userInteractionEnabled by default equal to NO. Just set it to YES to make the code works properly.

How to setup a subclass of UIScrollView to respond to touch events?

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.
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:
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.)

Resources