UIGestureRecognizer target issue - ios

I have a strange issue with UIGestureRecognizer
I've create a class where i declare the gesture recognizer, and put self as a target
-(id)initWithTextView:(UITextView*)theTextView withDelegate:(id<WordSelectionDelegate>)theDelegate
{
if (self = [super init])
{
delegate = theDelegate;
textView = theTextView;
// init long press gesture to detect pressing on text elements
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressFromSender:)];
[textView addGestureRecognizer:longPressGesture];
}
return self;
}
But the trick is when i actually make a long press gesture i have next error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableAttributedString handleLongPressFromSender:]: unrecognized selector sent to instance 0x76227b0'
Why does the messages to self goes to String???

By the way, the problem is undoubtedly that the object that has the handleLongPressFromSender instance method (i.e. the object you're initializing with initWithTextView) is falling out of scope by the time the UILongPressGestureRecognizer is invoked. You need to check the the scope of that object.
For example, assuming that the name of this class was MyTextViewHandler, imagine you had a viewDidLoad for some view controller that had something like:
- (void)viewDidLoad
{
[super viewDidLoad];
// do a bunch of initialization
MyTextViewHandler *textViewDelegate = [[MyTextViewHandler alloc] initWithTextView:self.textview withDelegate:self];
}
If you did something like that in ARC project, you'd get the crash you describe (because the textViewDelegate object was a local object of viewDidLoad and will fall out of scope at the end of that method). If you make this delegate handler class an instance variable (or property) of your view controller, then this problem goes away.

Related

initwithtarget:self where self is NSObject

Let's say that I want to create a GestureRecognizer object and have my whole logic in there. So when I add the NSObject as target for my recogniser:
initWithTarget:self action:#selector(doTheRecognizerThing:)
I'm facing an issue and I'm not sure why. I get an
unrecognized selector sent to instance
error although the doTheRecognizerThing method is properly implemented in my NSObject.
If I add the target and implement the method in any other object such as UIView or UIViewController I don't get any issues. Is there an explanation for that?
EDIT
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self
action:#selector(doTheRecognizerThing:)];
Implemantation
- (void) doTheRecognizerThing:(UIPanGestureRecognizer *)panGestureRecognizer {
//blah blah blah
}
Error Message:
-[CALayerArray doTheRecognizerThing:]: unrecognized selector sent to instance 0x14648a80
2015-01-06 23:05:20.788 Gestures[2203:1094298] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayerArray doTheRecognizerThing:]: unrecognized selector sent to instance 0x14648a80'
At one point you will add the recognizer to a view. This holds the recognizer strongly. At some point your object goes away, while the view stays – and with it the recognizer. That calls the method, but the object is gone and replaced by something else.
Try this:
initWithTarget:ObjectWithThatMethod action:#selector(doTheRecognizerThing:)
make sure doTheRecognizerThing is in header file.
And make sure that NSObject is not nil.

Message sent to deallocated object '_UITextTiledLayer' object

I have an UIScrollView with drawing on it's content view. I also have zoom functionality. I am adding UIView with UITextViews as its subview on zoom and removing UIView with UITextViews when user pinch out zoom. Sometimes it works fine but sometimes its crashing.
Also console continuous shows different combinations of these and more :
CALayerGetSuperlayer called on instance of UIScrollViewDelayedTouchesBeganGestureRecognizer
CALayerGetSuperlayer called on instance of __NSCFDictionary
CALayerGetSuperlayer called on instance of __NSArrayM
CALayerGetSuperlayer called on instance of __NSCFString
CALayerGetSuperlayer called on instance of __NSCFType
I have attached a screenshot of the instrument with zombies template. Which shows the summary of message sent to deallocated object.
Some of my code which will useful for solving this problem.
I am returning CATiledLayer to ensure zoomed content is sharp.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
tiledLayer.levelsOfDetail = 4;
tiledLayer.levelsOfDetailBias = 4;
}
return self;
}
+ layerClass
{
return [CATiledLayer class];
}
- (void)dealloc
{
CATiledLayer *tiledLayer = (CATiledLayer *)self.layer;
tiledLayer.contents=nil;
tiledLayer.delegate=nil;
[tiledLayer removeFromSuperlayer];
}
May be i'm wrong but, why do you instantiate a CATiledLayerin the dealloc method, this is physically wrong...
From what i know the reason of this error is either you are trying to dealloc an already deallocated object, or the object you are deallocating is empty

UIScrollView loses reference to delegate

I need to create a number of UIScrollViews dynamically and fill them with content. This is all good except when i set the delegate to self and pan the list i get this exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString scrollViewDidScroll:]: unrecognized selector sent to instance 0x7581230'
NSCFString obviously isn't my view controller (which implements the protocol UIScrollViewDelegate) so from what i gather somehow the memory gets messed up and it doesn't keep the reference correctly. Occasionally this can be something else too which strongly points to something being wrong with the memory
Here's the code to create the list:
for (NSUInteger i = 0; i < self.stories.currentStory.selectableWordCount; i++) {
UIScrollView *list = [[UIScrollView alloc] init];
list.alwaysBounceVertical = YES;
list.showsVerticalScrollIndicator = NO;
list.clipsToBounds = NO;
list.delegate = self;
list.pagingEnabled = YES;
[self.view addSubview:list];
.. // add UILabels to the list, set the frame, contentSize etc
[self.wordLists addObject:list]; // this is a #property (nonatomic, strong) NSMutableArray, declared in a private interface()
}
If i NSLog the delegate it's correct. respondsToSelector also matches fine. Interestingly if i comment out the scrollViewDidScroll: respondsToSelector: doesn't match any more and (probably because of this) the UIScrollView won't attempt to call this method any more. This then means that it can reach the delegate correctly to check for the method availability but when it gets called something goes wrong.
I'm targeting iOS5 with ARC. If this wasn't the case i would assume that i messed something up with the memory myself but now i don't have the same control.
I'm having a hard time debugging this issue, any help on how to proceed would be appreciated
D'uh. I was obviously looking in the wrong place. The view controller was added through a .xib and the view was pointing to a subview on the stage. However i needed to create an IBOutlet to the view controller in the main view controller to make sure it stays in memory. Hopefully this can help somebody else with a similar problem :)

kal delegate issue

I think setting the delegate for the KalViewController correctly - copying both the Holiday & NativeCal demo - but I must not be because I'm getting the following error when I click upon a date cell:
-[UINavigationButton didSelectDate:]: unrecognized selector sent to instance
When I set breakpoints on All Exceptions I see that it's raising an exception in KalGridView.m in this function:
- (void)setSelectedTile:(KalTileView *)tile
{
if (selectedTile != tile) {
selectedTile.selected = NO;
selectedTile = [tile retain];
tile.selected = YES;
[delegate didSelectDate:tile.date]; // exception raised here
}
}
And here's the code where I set the delegate (pretty much copied from the demo code):
- (void) viewDidLoad
{
KalViewController *calendar = [[KalViewController alloc] init];
calendar.delegate = self;
[[self.view viewWithTag:1] addSubview:calendar.view];
....}
The error makes sense because I'm setting the delegate to my own ViewController which doesn't implement didSelectDate. On the other hand, neither does the Holiday and NativeCal classes which are set at the KalViewController's delegate, both of which are of type
NSObject <UIApplicationDelegate, UITableViewDelegate>
Thanks a pile.. I'm more than a touch stuck.
This is one of those rare instances where the delegate should probably be retained because it's being released and replaced. Override -setDelegate: and retain your delegate.

Adding gestures to a shape - c4framework

I'm just learning how to use the C4 framework and trying to add gestures to a shape, but I can't seem to figure out how to get them to do anything. The following method creates an error, when I try to change the position of a button after it is tapped.
[buttonA addGesture:TAP name:#"tapGesture" action:#"setPosition"];
This is the error I get: * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyButton setPosition]: unrecognized selector sent to instance 0x7661b60'
I'm guessing that the reason you're getting the error is because the setPosition method is because you're trying to run the setPosition method directly on a C4Shape object. Natively, C4Shapes don't have this method.
In C4, all objects can have gestures attached to them, but in order run any custom code when you trigger a gesture on an object you should first subclass C4Shape and write a special method to handle the behaviour you want to see.
For example, I would create a MyShape class like this:
#interface MyShape : C4Shape
-(void)setNewPosition;
#end
#implementation MyShape
-(void)setNewPosition {
//will set the center of the shape to a new random point
self.center = CGPointMake([C4Math randomInt:768], [C4Math randomInt:1024]);
}
#end
Then, in my C4WorkSpace:
#import "C4WorkSpace.h"
#import "MyShape.h"
#implementation C4WorkSpace {
MyShape *newShape;
}
-(void)setup {
newShape = [MyShape new];
[newShape ellipse:CGRectMake(100, 100, 200, 200)];
[newShape addGesture:TAP name:#"tapGesture" action:#"setNewPosition"];
[self.canvas addShape:newShape];
}
#end
This should register a tap gesture with your new subclassed shape, and run its setNewPosition method when the gesture is triggered.
In order for the gesture to "send" the action you are trying to accomplish, you need to have a method named "setPositon" for the class "myButton". Do you have this method invoked in your code?

Resources