DidBeginContact in another class - objective-c

I whant to handle all my contacts in another class. I do not realy know how to do it, so I am doing it like this:
HandleContact is sub class of SKNode
-(void)didBeginContact:(SKPhysicsContact *)contact {
HandleContact *handleContact = [[HandleContact alloc]
initWithBodyA:contact.bodyA.node bodyB:contact.bodyB.node
scene:self];
}
Everything works as aspected, but i am getting this error:
Unused variable 'HandleContact'
So how should I do it in correct way ? (Maybe i should use another type? )

Your current code is a memory leak. Every time a contact is registered, you instantiate a HandleContact class. If you want to have a class to handle your contacts, I suggest you instantiate it at the beginning of your code and keep a reference to it. Some place like (void)didMoveToView:(SKView *)view
The question you need to ask yourself is why do you need a class to handle your contacts? You can call different methods from within didBeginContact if you are looking to organize your code.
-(void)didBeginContact:(SKPhysicsContact *)contact {
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (CategoryAlpha | CategoryBeta))
[self myMethod1];
}

Related

Cocoa user interface loading problems

I'm a noob on objective C so I'm sorry if I don't use the right terms to describe my problem but I need a hand and SO is my least resource!
I'm trying to interface an Arduino balance with my mac with an objective C software in which I've got a Nib file and a controller one: to do that I use ORSSerialPort which runs ok.
I'm experiencing some problems while loading a NSCombobox (the one with I make the user able to choose the serial port) after the user interface loading: in my controller class I have a method called "InitializeView" which calls this method:
-(void)RefreshSerialPortsInComboBox{
//Clear all existing elements
for (int i = 0; i < [self.serialPortsComboBox numberOfItems]; i++) {
[self.serialPortsComboBox removeItemAtIndex:i];
}
//Reload the serial ports list
NSArray *availableSerialPorts = [[NSArray alloc] initWithArray:[serialPortManager availablePorts]];
//Reload the Combobox elements with the new serial ports list
for (int i = 0; i < [availableSerialPorts count]; i++) {
[self.serialPortsComboBox addItemWithObjectValue:[[availableSerialPorts objectAtIndex:i] valueForKey:#"_path"]];
[self InsertTextInBufferTextView:#"Elemento creato...\n"];
}
}
The problem is that if I call this method in my controller object's init method, this doesn't work and the combobox items list is still empty: take note that the controller is instantiated by Interface Builder.
I tried to link the above method to a button and it works so it seems to be a matter of loading priority, it seems that I'm going to call the method before loading the ui objects or making them ready to be worked on...or maybe something else but I don't know what.
Can someone help me?
Another similar alternative just for completeness is to implement the method awakeFromNib, this method is called for all objects represented in a nib file. Its defined in the informal protocol NSNibAwaking
You should call this method in loadView method:
- (void)loadView {
[super loadView];
[self RefreshSerialPortsInComboBox];
}
Your code doesn't work because view and all IBOutlets haven't not initialized in "init" method yet.

Can you define a Class (objc_class) parameter to have a required subclass at compile time?

I have the following method:
- (FDModel *)_modelForClass: (Class)modelClass
withIdentifier: (NSString *)identifier
which should take in a Class and a identifier, create an instance of modelClass, assign the identifier and do some other work based on the fact that it assumed modelClass is a subclass of FDModel.
I can put in a check that raises some error or exception if [modelClass isSubclassOfClass: [FDModel class]] == NO but I was trying to see if there was a way to enforce this at compile time.
EDIT: I understand that some people see this as a obvious factory method but the modelClass parameter is actually passed in by the user of my library through a delegate callback - (Class<FDModel>)modelClassForDictionary: (NSDictionary *)dictionary;. This question was more aimed at making the user of my library return a Class that has a specific subclass.
I would consider the plain answer to your question being no; there is no way of checking if a class passed as a parameter is of a certain kind.
But I'd like to argue that the essence of your question primarily points to a design issue, i.e. can't your instance-generating method be expressed as a factory method? Like so:
#interface FDModel
+ (instancetype)modelWithIdentifier:(NSString *)identifier;
#end
In the above case you would simply do:
[FDModel modelWithIdentifier:anIdentifier];
The actual class returned (and the initialisation logic) being specified by the factory method implementation through subclassing of the FDModel class:
#implementation FDModelSubclass
+ (instancetype)modelWithIdentifier:(NSString *)identifier
{
FDModel *model = [super modelWithIdentifier:identifier];
if (model)
{
// do additional init stuff
}
return model;
}
#end
Nothing to check, no chance to go wrong.
After some research I don't think you can do it at compile time - you have to do it at runtime as you expected.
BOOL classConformsToProtocol = [class conformsToProtocol:#protocol(OKAProtocol)];
OR
BOOL classConformsToProtocol = [self class:[OKAClass class] conformsToProtocol:#"OKAProtocol"];
------
- (BOOL)class:(Class)class conformsToProtocol:(NSString *)protocol;
{
return [class conformsToProtocol:NSProtocolFromString(protocol)];
}

Calling subclass methods - Cocos2d

I'm working through the 'Learning Cocos2d' book, and I'm stuck on something basic.
So, theres a parent Class: GameplayLayer. In it, there's an 'init' method which creates an instance of the main character in here - 'Viking'. Viking is a subclass of 'GameCharacter', which is a subclass of 'GameObject'.
#pragma mark INIT PLAYER
Viking *viking = [[Viking alloc]
initWithSpriteFrame:[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#"viking.png"]];
[viking setJoystick:leftJoystick];
[viking setFireButton:fireButton];
[viking setSecondaryButton:secondaryButton];
[viking setCollisionLayer:collidableLayer]; // send collision layer to player
[viking setPosition:ccp(screenSize.width * 0.35f, screenSize.height * 0.14f)];
[viking setHealth:100];
[sceneSpriteBatchNode addChild:viking z:1000 tag:kPlayerSpriteTagValue];
Now, Viking has an update method which is called every frame by GameplayLayer. It's parent class, GameObject also has this update method, which brings up an error message if it is accidentally called - "GameObject update should be overridden'.
So in my code, I'm calling the update method of 'Viking' with the following method:
#pragma mark UPDATE_METHOD
-(void) update:(ccTime)deltaTime
{
CCArray *listOfGameObjects =
[sceneSpriteBatchNode children];
for (GameObject *tempChar in listOfGameObjects) {
CCLOG(#"engine found %#",tempChar);
[tempChar updateStateWithDeltaTime:deltaTime
andListOfGameObjects:listOfGameObjects];
}
}
So, this is supposed to call the 'updateStateWithDeltaTime' method in Viking. But somehow, it's calling the parent method in GameObject which says 'updatestate should be overridden'. How do I override the parent method?
Many thanks,
Carl
You need to cast tempChar to a Viking.
for (GameObject *tempChar in listOfGameObjects)
{
[(Viking *) tempChar updateStateWithDeltaTime:deltaTime
andListOfGameObjects:listOfGameObjects];
}
Because you're doing a for loop with fast enumeration of GameObjects, the local variable assumes that all objects are GameObjects. You need to explicitly cast tempChar to a Viking so that the program knows which class to look for the method in.
As an interesting side note, if GameObject didn't have the same method as Viking did, you would be getting a warning in XCode telling you it couldn't find the method you're asking for (because it needs to know that every object this could be called on has it).
You might want to check that the object you're calling this on is the correct class (if you only want to call this on Viking objects). You'd add if ([GameObject isKindOfClass[Viking class]) above your update method call.

Objective C custom class methods not being called

So I have this custom class with just a test method that does nslog. I am going to reuse this method many times in my app. The interface looks like this.
#interface TestViewController: UIViewController { CMImageMover * imageMover }
Then in the view did load I:
imageMover = [[CmImageMover alloc] init];
If I do:
[imageMover testMethod];
Right after the alloc and init it works in the viewDidLoad function but if I call it again from another function in the view controller nothing works and the class method does not get called.
What am I doing wrong here. Every other var I declare like NSArray/NSTimer, I do the say way and I am able to access and use it throughout my controller.
When you say "if I call it again from another function in the view controller nothing works" then first thing to check is what you are sending the testMethod. It could be nil, in which case nothing will happen. In objective C sending a message to nil does nothing. Add an NSLog to find out, e.g.
NSLog(#"imageMover object is: %#", imageOver);
[imageMover testMethod];
If the NSLog shows it is nil - or something crazy - then follow up what you are doing with the imageMover ivar.
You mention a class method in your question, but don't refer to it in your code snippets.
If you have defined testMethod as a class method it will, of course, fail if you send that message to an instance. (And it will fail noisily.) A class method would be introduced like this:
+ (void) testMethod
{
NSLog(#"CMImageMover testMethod called on Class");
}
An instance method would be introduced like this:
- (void) testMethod
{
NSLog(#"testMethod called on an instance of CMImageMover");
}
Apologies if this is all screamingly obvious to you and missing the point of the question. It's not that clear from your question where the issue lies.

Singleton Design

I'm creating a game that uses cards.
I have an AppController class with one instance in the nib.
The AppController instance has an NSArray instance variable called wordList.
On init, the nib's instance of AppController generates a new GameCard.
Every gamecard has an array of words containing 5 words selected at random from the the list in AppController.
Because the list is large, I'd like to read it into memory only once. Therefore, I want only one instance of AppController, as a singleton class. Every time a new GameCard is created from within AppController, it should access that same singleton instance to retrieve the wordlist.
So basically, I need a singleton AppController that creates GameCards, where each GameCard has a reference to the original AppController.
I'm not sure how to implement this. Sorry if the explanation was confusing.
A code example I found online follows (http://numbergrinder.com/node/29)
+ (AppController *)instance
{
static AppController *instance;
#synchronized(self) {
if(!instance) {
instance = [[AppController alloc] init];
}
}
return instance;
}
But when I tried to do something with it in a GameCard instance through the code below, my application took forever to launch and Xcode told me it was loading 99797 stack frames.
AppController *controller = [AppController instance];
It sounds like an infinite loop. Make sure that -[AppController init] isn't calling +[AppController instance].
Why does every card need a reference to the app controller?
If it's just to access its words, it's simpler to let each card own its words directly. Make a new method named initWithWords: the designated initializer for the GameCard class. Initialize each card with the array of its five words, and have the card own that array for its lifetime.
Removing the cards' references to the app controller would resolve the infinite loop that Tom astutely detected.
Also, if no word should appear on two cards at once, remember to take that into account when drawing from the app controller's Great Big Array Of Words, and when destroying cards (you may or may not want the words to go back into the pile for future cards).
It sounds like you're on the right track. I've never tried to put a reference to a singleton in a nib file, though. You may want to create a separate singleton class that maintains a copy of the data (DataManager, maybe?), and then call it from within your instance of AppController to fetch the words.
You may find that putting a singleton within a nib (using the code for a singleton in Stu's post) works just fine, though. Good luck!
It looks like you may be calling your class instance method from within your init method. Try something like this:
static AppController* _instance = nil;
- (id)init
{
// depending on your requirements, this may need locking
if( _instance ) {
[self release];
return _instance;
}
if( (self = [super init]) ) {
_instance = [self retain];
// do your initialization
}
return self;
}
+ (AppController*)instance
{
if( _instance ) return _instance;
else return [[AppController alloc] init];
}
This makes sure that only one instance of AppController is ever available and also that it's safe to allocate it as well as getting a copy through the instance class method. It's not thread safe, so if it's going to be accessed by multiple threads, you should add some locking around the checks to _instance.
The normal way to create an AppController/AppDelegate is to add a custom NSObject to your MainMenu/MainWindow.xib file. Set the class to be AppController. Link your UIApplication/NSApplication delegate reference to your AppController object. Then you can get your single AppController with either
(AppController*)[NSApp delegate];
or
(AppController*)[[UIApplication sharedApplication] delegate];
You never have to create it with alloc/init because it will be created when your application is launched. You don't have to worry about making it a singleton because no one will ever try to create another one. And you don't have to worry about how to access it because it will be the delegate of the UIApplication/NSApplication object.
All that said, if you need a global variable holding an array of words, then forget about the AppController and make a new singleton object which holds/reads the array. In which case you just need:
+ (NSArray *)sharedWordListArray
{
static NSArray *wordList;
if( !wordList ) {
wordList = [[NSMutableArray alloc] init];
// read array
}
return wordList;
}
If you really need thread safety, then simply call [WordList sharedWordListArray] from your app delegate's applicationDidFinishLaunching: method before starting any threads, or add an NSLock if you really want to defer the loading to later, but often its better to take the load time hit at the start of the program rather than unexpectedly when the user takes some later action.