Not casting properly? - ios

I'm following this tutorial. And I keep getting this casting error. I've imported the Obstacle.h file in the shown class (MainScene.m). I have no idea what I'm doing wrong
- (void)spawnNewObstacle {
CCNode *previousObstacle = [_obstacles lastObject];
CGFloat previousObstacleXPosition = previousObstacle.position.x;
if (!previousObstacle) {
// this is the first obstacle
previousObstacleXPosition = firstObstaclePosition;
}
Obstacle *obstacle = (Obstacle *)[CCBReader load:#"Obstacle"];
obstacle.position = ccp(previousObstacleXPosition + distanceBetweenObstacles, 0);
[obstacle setUpRandomPosition];
[_physicsNode addChild:obstacle];
[_obstacles addObject:obstacle];
}
Error:
-[CCNode setUpRandomPosition]: unrecognized selector sent to instance 0x9a88a30
2014-04-20 10:51:28.046 FlappyFlyl[2104:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CCNode setUpRandomPosition]: unrecognized selector sent to instance 0x9a88a30'

Likely you didn't set the custom class of your root node in "Obstacle.ccb" in SpriteBuilder correctly. That's why your "Obstacle.ccb" root node is a CCNode and not an Obstacle object.

The obstacle variable does not hold an object of type Obstacle. Instead it holds an object of type CCNode. CCNode does not have a method named -setUpRandomPosition, so you get a runtime error. In Objective-C, casting is a no-op. It doesn't do anything except helping the reader of your code see the intent of the person who wrote the code.
In this regard Objective-C differs from languages like C++ or Java. Objective-C has an object system that is similar to the programming language "Smalltalk".

Related

After migrating to Swift 3, crash on accessing ViewController's view

After migrating to Swift 3, the app crashes on
-[_SwiftValue unsignedIntegerValue]: unrecognized selector sent to instance 0x60800064d5f0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue unsignedIntegerValue]: unrecognized selector sent to instance 0x60800064d5f0'
When trying to access vc.view. Here is the relevant code snippet. The code is called from a UIViewController.
guard let vc = storyboard?.instantiateViewController(withIdentifier: "some-viewcontroller-id") else {
return
}
if let vc = vc as? SomeViewController {
let theView: UIView = vc.view
theView.translatesAutoresizingMaskIntoConstraints = false
}
If I stop on breakpoint before calling let theView: UIView = vc.view and po vc.view in the debug window, I get the same error in the debug window.
-[_SwiftValue unsignedIntegerValue]: unrecognized selector sent to instance
BUT if I po vc.view again I get... voilĂ ...
Optional<UIView>
and the execution can be resumed. I am using Xcode 8.1. Reproduces both on iOS device and simulator.
Any suggestions?
I think it's not due to UIViewController.view. Your error says that it's Unrecognized Selector send to instance allocating at some kind of memory index. If one of ur selector method is private, put #objc in front of it. I can surely say it's not the Nil value error.
Make the storyboard-id of the view as "some-viewcontroller-id"
and it would work fine
ISSUE RESOLVED
To make a long story short, it is not related to UIViewController.view at all! It is related to the String.Encoding.utf8.rawValue issue described in this answer.
For some reason the crash on simulator didn't give much info except for I already pasted into the question. On device, it produced a much detailed report that helped me find the root cause of this crash.

Finding nearest points with Chipmunk and cocos2d

Using cocos2d and chipmunk, I try to get the different object around a sprite (for example a bomb) so that I can apply an impulse on these. I first added this on top of my project:
#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
#import "CCPhysics+ObjectiveChipmunk.h"
And then the code:
ChipmunkSpace *space = [_physicsNode space];
cpVect origin = item.position;
for(ChipmunkPointQueryInfo *info in [space pointQueryNearest:origin maxDistance:32.0f filter:CP_SHAPE_FILTER_ALL])
{
CCLOG(#"Found one body");
}
I receive this error:
-[ChipmunkPointQueryInfo countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x813cdca0
What's the problem ?
You code should be
ChipmunkPointQueryInfo *info=[space pointQueryNearest:origin maxDistance:32.0f filter:CP_SHAPE_FILTER_ALL];
pointQueryNearest doesn't return array, as you are trying to enumerate.
Cheers.

selector syntax: why I am getting unrecognized selector error?

I have a method to compare 2 objects:
- (NSComparisonResult)compare:(NSObject *)object1 to:(NSObject *)object2{
// do some stuff
return NSOrderedSame; // or NSOrderedAscending or NSOrderedDescending
}
This method gets called like this:
NSArray *sortedSyncedAufgaben = [syncedAufgabe sortedArrayUsingSelector:#selector(compare:to:)];
Now, when I run this on my iPhone, a "unrecognized selector error" is thrown in the line with the selector:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ImpfVorgang compare:to:]: unrecognized selector sent to instance 0x14ebf040'
What is wrong? I thought for each parameter I need a colon?
sortedArrayUsingSelector: tries to apply you selector to the object on the left-hand side of the comparison, not to the class that calls sortedArrayUsingSelector:. In other words, if the selector exists in your class that initiates the sort, not in the class of the object inside NSArray (i.e. not in your ImpfVorgang class), you are going to see an "unrecognized selector error".
You can change your code to apply the selector manually, like this:
NSArray * sortedSyncedAufgaben = [syncedAufgabe sortedArrayUsingComparator:^(NSObject *a, NSObject* b) {
return [self compare:a to:b];
}];
Alternatively, you could move the comparison logic into the comparator block, and drop the compare:to: method altogether.

GenericException : Collection was mutated while being enumerated

I have searched for this problem and I know it is caused because an array is manipulated while its enumeration. Earlier in my code, I was using :
-(BOOL)busy
{
for(DataRequest* request in self.active)
if(!request.invisible)
return YES;
return NO;
}
and -(BOOL)busy is being called very frequently as the data loads from the server. Also in my code I have some lines which adds and removes objects in self.active. And because of this I was getting the exception. Then I made a change in the code as:
-(BOOL)busy
{
self.tempActive = self.active;
for(DataRequest* request in _tempActive)
if(!request.invisible)
return YES;
return NO;
}
but I am still getting the same exception. What am I doing wrong, any ideas? This is the only code where self.tempActive is used.
The exception I am getting is:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x9ec8f60> was mutated while being enumerated.'
You need to understand the difference between classes and stack objects (like ints and things). Setting something equal to something else does not make a copy of it if it is a class. You need to use [self.active copy] instead.

Connect to an IOS IBAction which is not at a "valid connection destination"

I have been spending days to make connection from a button on the storyboard to a new NSObject class in an IOS project. Methods I used in OS X no longer work in IOS.
I have no trouble connection the button to the IBAction on the original UIViewController class. According to the Apple documentation my new class is not a "valid connection destination".
To work around the issue I tried to call the method in the new class from the UIViewController class. I tried notification and delegate schemes, using the posts on Stack Overflow, but could not get them to work.
The closest I came linking to a +method in the target class, such as
+ (void) startToneGenerator
{
NSLog(#"Arrived in startToneGenerator");
// [self startPlay:nil];
}
However, from inside that method I can not call the -startPlay in the same class. Because the -StartPlay class is part of an audio unit construct I can not change it to a +starPlay class without breaking the audio unit.
Can anyone point me to some documentation which describes what "valid connection destination" really means, and how to make the attempted connection a valid one.
I used the method suggested in answer 1 in OS X, where it does work, but it no longer works in IOS.
I am restating the code you clarify the problem.
// code in VC
- (IBAction)RunPauseStop:(id)sender
{
NSLog(#"arrived in RunPauseSTop"); // OK
[uToneGenerator testMethod]; // OK
// [uToneGenerator startPlay:self]; // crashes
}
// code in uToneGenerator
+ (void) testMethod
{
NSLog(#"arrived in <testMethod>"); // OK
// [uToneGenerator startPlay:nil]; // crashes
}
- (IBAction)startPlay:(id)sender
{
NSLog(#"arrived in <startPlay>"); // Don't get here
}
The line [uToneGenerator startPlay:nil]; compiles (with a warning) but crashes with:
2012-03-06 13:20:25.509 Tinnitus Tamer IP[863:f803] +[uToneGenerator startPlay:]: unrecognized selector sent to class 0x6c40
2012-03-06 13:20:25.509 Tinnitus Tamer IP[863:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[uToneGenerator startPlay:]: unrecognized selector sent to class 0x6c40'
calling from testMethod; compiles but crashes with:
2012-03-06 13:22:31.413 Tinnitus Tamer IP[885:f803] +[uToneGenerator startPlay:]: unrecognized selector sent to class 0x6c44
2012-03-06 13:22:31.414 Tinnitus Tamer IP[885:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[uToneGenerator startPlay:]: unrecognized selector sent to class 0x6c44'
I noted that the error message can not find +[uToneGenerator startPlay:, but the method I am trying to call is -[uToneGenerator startPlay:
uToneGenerator *utg = [[uToneGenerator alloc]init]; works OK. In spite of the compiler warning "NSProject may not respond to 'startPlay'.
Thanks for helping me out. Much appreciated. I really was stuck.
You need to call whatever class method you want inside the IBAction method in your VC:
- (IBAction)myButtonPressed:(id)sender {
[MyClass myClassMethod];
}
If you want that code to work you must declare - (IBAction)startPlay:(id)sender with a +. Otherwise you will have to make an instance of your class:
uToneGenerator *utg = [[uToneGenerator alloc]init]; //or whatever you use
and then use that to call your startPlay method:
[utg startPlay:self];
Hope it helps.

Resources